Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
O
OpenXG-SMF-Simple
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
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
CommunityXG
OpenXG-SMF-Simple
Commits
a9935948
Commit
a9935948
authored
Jan 27, 2021
by
Tien-Thinh Nguyen
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Code cleanup after testing
parent
93911a2a
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
776 additions
and
1246 deletions
+776
-1246
src/smf_app/smf_app.cpp
src/smf_app/smf_app.cpp
+3
-3
src/smf_app/smf_context.cpp
src/smf_app/smf_context.cpp
+624
-1193
src/smf_app/smf_context.hpp
src/smf_app/smf_context.hpp
+149
-50
No files found.
src/smf_app/smf_app.cpp
View file @
a9935948
...
...
@@ -631,10 +631,10 @@ void smf_app::handle_pdu_session_create_sm_context_request(
PDU_SESSION_TYPE_E_IPV4
};
// Step 1. Decode NAS and get the necessary information
// std::string n1_sm_msg = smreq->req.get_n1_sm_message();
// std::string n1_sm_msg = smreq->req.get_n1_sm_message();
int
decoder_rc
=
smf_n1
::
get_instance
().
decode_n1_sm_container
(
decoded_nas_msg
,
smreq
->
req
.
get_n1_sm_message
());
int
decoder_rc
=
smf_n1
::
get_instance
().
decode_n1_sm_container
(
decoded_nas_msg
,
smreq
->
req
.
get_n1_sm_message
());
// Failed to decode, send reply to AMF with PDU Session Establishment Reject
if
(
decoder_rc
!=
RETURNok
)
{
...
...
src/smf_app/smf_context.cpp
View file @
a9935948
...
...
@@ -1198,8 +1198,8 @@ void smf_context::handle_pdu_session_create_sm_context_request(
bool
request_accepted
=
true
;
// Step 1. get necessary information
std
::
string
dnn
=
smreq
->
req
.
get_dnn
();
snssai_t
snssai
=
smreq
->
req
.
get_snssai
();
std
::
string
dnn
=
smreq
->
req
.
get_dnn
();
snssai_t
snssai
=
smreq
->
req
.
get_snssai
();
supi64_t
supi64
=
smf_supi_to_u64
(
smreq
->
req
.
get_supi
());
uint32_t
pdu_session_id
=
smreq
->
req
.
get_pdu_session_id
();
...
...
@@ -1553,676 +1553,657 @@ void smf_context::handle_pdu_session_create_sm_context_request(
}
}
bool
smf_context
::
handle_pdu_session_modification_request
(
nas_message_t
&
nas_msg
,
std
::
shared_ptr
<
itti_n11_update_sm_context_request
>
&
sm_context_request
,
std
::
shared_ptr
<
itti_n11_update_sm_context_response
>
&
sm_context_resp
,
std
::
shared_ptr
<
smf_pdu_session
>
&
sp
)
{
// PDU Session Modification procedure (UE-initiated, step 1.a,
// Section 4.3.3.2@3GPP TS 23.502) UE initiated PDU session
// modification request (Step 1)
Logger
::
smf_app
().
debug
(
"PDU_SESSION_MODIFICATION_REQUEST"
);
sm_context_resp
.
get
()
->
session_procedure_type
=
session_management_procedures_type_e
::
PDU_SESSION_MODIFICATION_UE_INITIATED_STEP1
;
// check if the PDU Session Release Command is already sent for this
// message (see section 6.3.3.5 @3GPP TS 24.501)
if
(
sp
.
get
()
->
get_pdu_session_status
()
==
pdu_session_status_e
::
PDU_SESSION_INACTIVE_PENDING
)
{
// Ignore the message
Logger
::
smf_app
().
info
(
"A PDU Session Release Command has been sent for this session "
"(session ID %d), ignore the message!"
,
nas_msg
.
plain
.
sm
.
header
.
pdu_session_identity
);
return
false
;
}
// check if the session is in state Modification pending, SMF will
// ignore this message (see section 6.3.2.5 @3GPP TS 24.501)
if
(
sp
.
get
()
->
get_pdu_session_status
()
==
pdu_session_status_e
::
PDU_SESSION_MODIFICATION_PENDING
)
{
// Ignore the message
Logger
::
smf_app
().
info
(
"This PDU session is in MODIFICATION_PENDING State (session ID "
"%d), ignore the message!"
,
nas_msg
.
plain
.
sm
.
header
.
pdu_session_identity
);
return
false
;
}
//-------------------------------------------------------------------------------------
bool
smf_context
::
handle_pdu_session_modification_request
(
nas_message_t
&
nas_msg
,
std
::
shared_ptr
<
itti_n11_update_sm_context_request
>&
sm_context_request
,
std
::
shared_ptr
<
itti_n11_update_sm_context_response
>&
sm_context_resp
,
std
::
shared_ptr
<
smf_pdu_session
>&
sp
)
{
Logger
::
smf_app
().
debug
(
"PDU_SESSION_MODIFICATION_REQUEST"
);
// See section 6.4.2 - UE-requested PDU Session modification procedure@
// 3GPP TS 24.501 Verify PDU Session Identity
if
(
sm_context_request
.
get
()
->
req
.
get_pdu_session_id
()
!=
nas_msg
.
plain
.
sm
.
header
.
pdu_session_identity
)
{
// TODO: PDU Session ID mismatch
}
sm_context_resp
.
get
()
->
session_procedure_type
=
session_management_procedures_type_e
::
PDU_SESSION_MODIFICATION_UE_INITIATED_STEP1
;
// PTI
// check if the PDU Session Release Command is already sent for this
// message (see section 6.3.3.5 @3GPP TS 24.501)
if
(
sp
.
get
()
->
get_pdu_session_status
()
==
pdu_session_status_e
::
PDU_SESSION_INACTIVE_PENDING
)
{
// Ignore the message
Logger
::
smf_app
().
info
(
"PTI %d"
,
nas_msg
.
plain
.
sm
.
header
.
procedure_transaction_identity
);
procedure_transaction_id_t
pti
=
{
.
procedure_transaction_id
=
nas_msg
.
plain
.
sm
.
header
.
procedure_transaction_identity
};
sm_context_resp
.
get
()
->
res
.
set_pti
(
pti
);
// Message Type
// TODO: _5GSMCapability
// TODO: Cause
// TODO: maximum_number_of_supported_packet_filters
// TODO: AlwaysonPDUSessionRequested
// TODO: IntergrityProtectionMaximumDataRate
// Process QoS rules and Qos Flow descriptions
update_qos_info
(
sp
,
sm_context_resp
.
get
()
->
res
,
nas_msg
);
// TODO: MappedEPSBearerContexts
// TODO: ExtendedProtocolConfigurationOptions
// section 6.3.2. Network-requested PDU Session modification procedure @
// 3GPP TS 24.501 requested QoS rules (including packet filters) and/or
// requested QoS flow descriptions session-AMBR, session TMBR
// PTI or UE capability
// Create a N1 SM (PDU Session Modification Command) and N2 SM (PDU
// Session Resource Modify Request Transfer IE)
std
::
string
n1_sm_msg_to_be_created
,
n1_sm_msg_hex_to_be_created
;
std
::
string
n2_sm_info_to_be_created
,
n2_sm_info_hex_to_be_created
;
// N1 SM (PDU Session Modification Command)
if
(
not
smf_n1
::
get_instance
()
.
create_n1_pdu_session_modification_command
(
sm_context_resp
.
get
()
->
res
,
n1_sm_msg_to_be_created
,
cause_value_5gsm_e
::
CAUSE_0_UNKNOWN
)
or
// N2 SM (PDU Session Resource Modify Request Transfer IE)
not
smf_n2
::
get_instance
()
.
create_n2_pdu_session_resource_modify_request_transfer
(
sm_context_resp
.
get
()
->
res
,
n2_sm_info_type_e
::
PDU_RES_MOD_REQ
,
n2_sm_info_to_be_created
))
{
smf_app_inst
->
trigger_http_response
(
http_status_code_e
::
HTTP_STATUS_CODE_500_INTERNAL_SERVER_ERROR
,
sm_context_request
.
get
()
->
pid
,
N11_SESSION_UPDATE_SM_CONTEXT_RESPONSE
);
"A PDU Session Release Command has been sent for this session "
"(session ID %d), ignore the message!"
,
nas_msg
.
plain
.
sm
.
header
.
pdu_session_identity
);
return
false
;
}
// free_wrapper((void **)&qos_flow_description);
free_wrapper
((
void
**
)
&
nas_msg
.
plain
.
sm
.
pdu_session_modification_request
.
qosflowdescriptions
.
qosflowdescriptionscontents
);
return
false
;
}
// check if the session is in state Modification pending, SMF will
// ignore this message (see section 6.3.2.5 @3GPP TS 24.501)
if
(
sp
.
get
()
->
get_pdu_session_status
()
==
pdu_session_status_e
::
PDU_SESSION_MODIFICATION_PENDING
)
{
// Ignore the message
Logger
::
smf_app
().
info
(
"This PDU session is in MODIFICATION_PENDING State (session ID "
"%d), ignore the message!"
,
nas_msg
.
plain
.
sm
.
header
.
pdu_session_identity
);
return
false
;
}
smf_app_inst
->
convert_string_2_hex
(
n1_sm_msg_to_be_created
,
n1_sm_msg_hex_to_be_created
);
smf_app_inst
->
convert_string_2_hex
(
n2_sm_info_to_be_created
,
n2_sm_info_hex_to_be_created
);
// See section 6.4.2 - UE-requested PDU Session modification procedure@
// 3GPP TS 24.501 Verify PDU Session Identity
if
(
sm_context_request
.
get
()
->
req
.
get_pdu_session_id
()
!=
nas_msg
.
plain
.
sm
.
header
.
pdu_session_identity
)
{
// TODO: PDU Session ID mismatch
}
sm_context_resp
.
get
()
->
res
.
set_n1_sm_message
(
n1_sm_msg_hex_to_be_created
);
sm_context_resp
.
get
()
->
res
.
set_n2_sm_information
(
n2_sm_info_hex_to_be_created
);
sm_context_resp
.
get
()
->
res
.
set_n2_sm_info_type
(
"PDU_RES_MOD_REQ"
);
// PTI
Logger
::
smf_app
().
info
(
"PTI %d"
,
nas_msg
.
plain
.
sm
.
header
.
procedure_transaction_identity
);
procedure_transaction_id_t
pti
=
{
.
procedure_transaction_id
=
nas_msg
.
plain
.
sm
.
header
.
procedure_transaction_identity
};
sm_context_resp
.
get
()
->
res
.
set_pti
(
pti
);
// Message Type
// TODO: _5GSMCapability
// TODO: Cause
// TODO: maximum_number_of_supported_packet_filters
// TODO: AlwaysonPDUSessionRequested
// TODO: IntergrityProtectionMaximumDataRate
// Fill the json part
nlohmann
::
json
json_data
=
{};
// N1SM
json_data
[
"n1MessageContainer"
][
"n1MessageClass"
]
=
N1N2_MESSAGE_CLASS
;
json_data
[
"n1MessageContainer"
][
"n1MessageContent"
][
"contentId"
]
=
N1_SM_CONTENT_ID
;
json_data
[
"n2InfoContainer"
][
"n2InformationClass"
]
=
N1N2_MESSAGE_CLASS
;
json_data
[
"n2InfoContainer"
][
"smInfo"
][
"n2InfoContent"
][
"ngapIeType"
]
=
"PDU_RES_MOD_REQ"
;
// NGAP message
json_data
[
"n2InfoContainer"
][
"smInfo"
][
"n2InfoContent"
][
"ngapData"
]
[
"contentId"
]
=
N2_SM_CONTENT_ID
;
json_data
[
"n2InfoContainer"
][
"smInfo"
][
"PduSessionId"
]
=
sm_context_resp
.
get
()
->
res
.
get_pdu_session_id
();
sm_context_resp
.
get
()
->
res
.
set_json_data
(
json_data
);
// Update PDU Session status
sp
.
get
()
->
set_pdu_session_status
(
pdu_session_status_e
::
PDU_SESSION_MODIFICATION_PENDING
);
// start timer T3591
// get smf_pdu_session and set the corresponding timer
sp
.
get
()
->
timer_T3591
=
itti_inst
->
timer_setup
(
T3591_TIMER_VALUE_SEC
,
0
,
TASK_SMF_APP
,
TASK_SMF_APP_TRIGGER_T3591
,
sm_context_request
.
get
()
->
req
.
get_pdu_session_id
());
// Process QoS rules and Qos Flow descriptions
update_qos_info
(
sp
,
sm_context_resp
.
get
()
->
res
,
nas_msg
);
// TODO: MappedEPSBearerContexts
// TODO: ExtendedProtocolConfigurationOptions
// section 6.3.2. Network-requested PDU Session modification procedure @
// 3GPP TS 24.501 requested QoS rules (including packet filters) and/or
// requested QoS flow descriptions session-AMBR, session TMBR
// PTI or UE capability
// Create a N1 SM (PDU Session Modification Command) and N2 SM (PDU
// Session Resource Modify Request Transfer IE)
std
::
string
n1_sm_msg_to_be_created
,
n1_sm_msg_hex_to_be_created
;
std
::
string
n2_sm_info_to_be_created
,
n2_sm_info_hex_to_be_created
;
// N1 SM (PDU Session Modification Command)
if
(
not
smf_n1
::
get_instance
().
create_n1_pdu_session_modification_command
(
sm_context_resp
.
get
()
->
res
,
n1_sm_msg_to_be_created
,
cause_value_5gsm_e
::
CAUSE_0_UNKNOWN
)
or
// N2 SM (PDU Session Resource Modify Request Transfer IE)
not
smf_n2
::
get_instance
()
.
create_n2_pdu_session_resource_modify_request_transfer
(
sm_context_resp
.
get
()
->
res
,
n2_sm_info_type_e
::
PDU_RES_MOD_REQ
,
n2_sm_info_to_be_created
))
{
smf_app_inst
->
trigger_http_response
(
http_status_code_e
::
HTTP_STATUS_CODE_500_INTERNAL_SERVER_ERROR
,
sm_context_request
.
get
()
->
pid
,
N11_SESSION_UPDATE_SM_CONTEXT_RESPONSE
);
//sm_context_resp.get()->session_procedure_type = sm_context_resp.get()->session_procedure_type;
// don't need to create a procedure to update UPF
free_wrapper
((
void
**
)
&
nas_msg
.
plain
.
sm
.
pdu_session_modification_request
.
qosflowdescriptions
.
qosflowdescriptionscontents
);
return
false
;
}
free_wrapper
(
(
void
**
)
&
nas_msg
.
plain
.
sm
.
pdu_session_modification_request
.
qosflowdescriptions
.
qosflowdescriptionscontents
);
smf_app_inst
->
convert_string_2_hex
(
n1_sm_msg_to_be_created
,
n1_sm_msg_hex_to_be_created
);
smf_app_inst
->
convert_string_2_hex
(
n2_sm_info_to_be_created
,
n2_sm_info_hex_to_be_created
);
sm_context_resp
.
get
()
->
res
.
set_n1_sm_message
(
n1_sm_msg_hex_to_be_created
);
sm_context_resp
.
get
()
->
res
.
set_n2_sm_information
(
n2_sm_info_hex_to_be_created
);
sm_context_resp
.
get
()
->
res
.
set_n2_sm_info_type
(
"PDU_RES_MOD_REQ"
);
// Fill the json part
nlohmann
::
json
json_data
=
{};
// N1SM
json_data
[
"n1MessageContainer"
][
"n1MessageClass"
]
=
N1N2_MESSAGE_CLASS
;
json_data
[
"n1MessageContainer"
][
"n1MessageContent"
][
"contentId"
]
=
N1_SM_CONTENT_ID
;
json_data
[
"n2InfoContainer"
][
"n2InformationClass"
]
=
N1N2_MESSAGE_CLASS
;
json_data
[
"n2InfoContainer"
][
"smInfo"
][
"n2InfoContent"
][
"ngapIeType"
]
=
"PDU_RES_MOD_REQ"
;
// NGAP message
json_data
[
"n2InfoContainer"
][
"smInfo"
][
"n2InfoContent"
][
"ngapData"
]
[
"contentId"
]
=
N2_SM_CONTENT_ID
;
json_data
[
"n2InfoContainer"
][
"smInfo"
][
"PduSessionId"
]
=
sm_context_resp
.
get
()
->
res
.
get_pdu_session_id
();
sm_context_resp
.
get
()
->
res
.
set_json_data
(
json_data
);
// Update PDU Session status
sp
.
get
()
->
set_pdu_session_status
(
pdu_session_status_e
::
PDU_SESSION_MODIFICATION_PENDING
);
// start timer T3591
// get smf_pdu_session and set the corresponding timer
sp
.
get
()
->
timer_T3591
=
itti_inst
->
timer_setup
(
T3591_TIMER_VALUE_SEC
,
0
,
TASK_SMF_APP
,
TASK_SMF_APP_TRIGGER_T3591
,
sm_context_request
.
get
()
->
req
.
get_pdu_session_id
());
free_wrapper
((
void
**
)
&
nas_msg
.
plain
.
sm
.
pdu_session_modification_request
.
qosflowdescriptions
.
qosflowdescriptionscontents
);
return
true
;
}
bool
smf_context
::
handle_pdu_session_modification_complete
(
nas_message_t
&
nas_msg
,
std
::
shared_ptr
<
itti_n11_update_sm_context_request
>
&
sm_context_request
,
std
::
shared_ptr
<
itti_n11_update_sm_context_response
>
&
sm_context_resp
,
std
::
shared_ptr
<
smf_pdu_session
>
&
sp
)
{
//-------------------------------------------------------------------------------------
bool
smf_context
::
handle_pdu_session_modification_complete
(
nas_message_t
&
nas_msg
,
std
::
shared_ptr
<
itti_n11_update_sm_context_request
>&
sm_context_request
,
std
::
shared_ptr
<
itti_n11_update_sm_context_response
>&
sm_context_resp
,
std
::
shared_ptr
<
smf_pdu_session
>&
sp
)
{
/* see section 6.3.2.3@3GPP TS 24.501 V16.1.0
Upon receipt of a PDU SESSION MODIFICATION COMPLETE message, the SMF
shall stop timer T3591 and shall consider the PDU session as modified.
If the selected SSC mode of the PDU session is "SSC mode 3" and the PDU
SESSION MODIFICATION COMMAND message included 5GSM cause #39
"reactivation requested", the SMF shall start timer T3593. If the PDU
Session Address Lifetime value is sent to the UE in the PDU SESSION
MODIFICATION COMMAND message then timer T3593 shall be started with the
same value, otherwise it shall use a default value.
*/
// Update PDU Session status -> ACTIVE
sp
.
get
()
->
set_pdu_session_status
(
pdu_session_status_e
::
PDU_SESSION_ACTIVE
);
// stop T3591
itti_inst
->
timer_remove
(
sp
.
get
()
->
timer_T3591
);
sm_context_resp
.
get
()
->
session_procedure_type
=
session_management_procedures_type_e
::
PDU_SESSION_MODIFICATION_UE_INITIATED_STEP3
;
return
true
;
}
//-------------------------------------------------------------------------------------
bool
smf_context
::
handle_pdu_session_modification_command_reject
(
nas_message_t
&
nas_msg
,
std
::
shared_ptr
<
itti_n11_update_sm_context_request
>&
sm_context_request
,
std
::
shared_ptr
<
itti_n11_update_sm_context_response
>&
sm_context_resp
,
std
::
shared_ptr
<
smf_pdu_session
>&
sp
)
{
sm_context_resp
.
get
()
->
session_procedure_type
=
session_management_procedures_type_e
::
PDU_SESSION_MODIFICATION_UE_INITIATED_STEP3
;
/* see section 6.3.2.3@3GPP TS 24.501 V16.1.0
Upon receipt of a PDU SESSION MODIFICATION COMPLETE message, the SMF
shall stop timer T3591 and shall consider the PDU session as modified.
If the selected SSC mode of the PDU session is "SSC mode 3" and the PDU
SESSION MODIFICATION COMMAND message included 5GSM cause #39
"reactivation requested", the SMF shall start timer T3593. If the PDU
Session Address Lifetime value is sent to the UE in the PDU SESSION
MODIFICATION COMMAND message then timer T3593 shall be started with the
same value, otherwise it shall use a default value.
*/
// Update PDU Session status -> ACTIVE
// Verify PDU Session Identity
if
(
sm_context_request
.
get
()
->
req
.
get_pdu_session_id
()
!=
nas_msg
.
plain
.
sm
.
header
.
pdu_session_identity
)
{
// TODO: PDU Session ID mismatch
}
Logger
::
smf_app
().
info
(
"PTI %d"
,
nas_msg
.
plain
.
sm
.
header
.
procedure_transaction_identity
);
procedure_transaction_id_t
pti
=
{
.
procedure_transaction_id
=
nas_msg
.
plain
.
sm
.
header
.
procedure_transaction_identity
};
sm_context_resp
.
get
()
->
res
.
set_pti
(
pti
);
// Message Type
//_5GSMCause
// presence
// ExtendedProtocolConfigurationOptions
if
(
nas_msg
.
plain
.
sm
.
pdu_session_modification_command_reject
.
_5gsmcause
==
static_cast
<
uint8_t
>
(
cause_value_5gsm_e
::
CAUSE_43_INVALID_PDU_SESSION_IDENTITY
))
{
// Update PDU Session status -> INACTIVE
sp
.
get
()
->
set_pdu_session_status
(
pdu_session_status_e
::
PDU_SESSION_ACTIVE
);
// stop T3591
itti_inst
->
timer_remove
(
sp
.
get
()
->
timer_T3591
);
pdu_session_status_e
::
PDU_SESSION_INACTIVE
);
// TODO: Release locally the existing PDU Session (see
// section 6.3.2.5@3GPP TS 24.501)
}
else
if
(
sp
.
get
()
->
get_pdu_session_status
()
==
pdu_session_status_e
::
PDU_SESSION_MODIFICATION_PENDING
)
{
// Update PDU Session status -> ACTIVE
sp
.
get
()
->
set_pdu_session_status
(
pdu_session_status_e
::
PDU_SESSION_ACTIVE
);
}
sm_context_resp
.
get
()
->
session_procedure_type
=
session_management_procedures_type_e
::
PDU_SESSION_MODIFICATION_UE_INITIATED_STEP3
;
// don't need to create a procedure to update UPF
// stop T3591
itti_inst
->
timer_remove
(
sp
.
get
()
->
timer_T3591
);
return
true
;
}
bool
smf_context
::
handle_pdu_session_modification_command_reject
(
nas_message_t
&
nas_msg
,
std
::
shared_ptr
<
itti_n11_update_sm_context_request
>
&
sm_context_request
,
std
::
shared_ptr
<
itti_n11_update_sm_context_response
>
&
sm_context_resp
,
std
::
shared_ptr
<
smf_pdu_session
>
&
sp
)
{
//-------------------------------------------------------------------------------------
bool
smf_context
::
handle_pdu_session_release_request
(
nas_message_t
&
nas_msg
,
std
::
shared_ptr
<
itti_n11_update_sm_context_request
>&
sm_context_request
,
std
::
shared_ptr
<
itti_n11_update_sm_context_response
>&
sm_context_resp
,
std
::
shared_ptr
<
smf_pdu_session
>&
sp
)
{
std
::
string
n1_sm_msg
,
n1_sm_msg_hex
;
std
::
string
n2_sm_info
,
n2_sm_info_hex
;
sm_context_resp
.
get
()
->
session_procedure_type
=
session_management_procedures_type_e
::
PDU_SESSION_MODIFICATION_UE_INITIATED_STEP3
;
sm_context_resp
.
get
()
->
session_procedure_type
=
session_management_procedures_type_e
::
PDU_SESSION_RELEASE_UE_REQUESTED_STEP1
;
// Verify PDU Session Identity
if
(
sm_context_request
.
get
()
->
req
.
get_pdu_session_id
()
!=
nas_msg
.
plain
.
sm
.
header
.
pdu_session_identity
)
{
// TODO: PDU Session ID mismatch
}
// verify PDU Session ID
if
(
sm_context_request
.
get
()
->
req
.
get_pdu_session_id
()
!=
nas_msg
.
plain
.
sm
.
header
.
pdu_session_identity
)
{
// TODO: PDU Session ID mismatch
}
Logger
::
smf_app
().
info
(
"PTI %d"
,
nas_msg
.
plain
.
sm
.
header
.
procedure_transaction_identity
);
procedure_transaction_id_t
pti
=
{
.
procedure_transaction_id
=
nas_msg
.
plain
.
sm
.
header
.
procedure_transaction_identity
};
sm_context_resp
.
get
()
->
res
.
set_pti
(
pti
);
// Abnormal cases in network side (see section 6.4.3.6 @3GPP TS 24.501)
if
(
sp
.
get
()
->
get_pdu_session_status
()
==
pdu_session_status_e
::
PDU_SESSION_INACTIVE
)
{
Logger
::
smf_app
().
warn
(
"PDU Session status: INACTIVE, send PDU Session Release Reject "
"to UE!"
);
if
(
smf_n1
::
get_instance
().
create_n1_pdu_session_release_reject
(
sm_context_request
.
get
()
->
req
,
n1_sm_msg
,
cause_value_5gsm_e
::
CAUSE_43_INVALID_PDU_SESSION_IDENTITY
))
{
smf_app_inst
->
convert_string_2_hex
(
n1_sm_msg
,
n1_sm_msg_hex
);
// trigger to send reply to AMF
smf_app_inst
->
trigger_update_context_error_response
(
http_status_code_e
::
HTTP_STATUS_CODE_403_FORBIDDEN
,
PDU_SESSION_APPLICATION_ERROR_NETWORK_FAILURE
,
n1_sm_msg_hex
,
sm_context_request
.
get
()
->
pid
);
}
else
{
smf_app_inst
->
trigger_http_response
(
http_status_code_e
::
HTTP_STATUS_CODE_500_INTERNAL_SERVER_ERROR
,
sm_context_request
.
get
()
->
pid
,
N11_SESSION_UPDATE_SM_CONTEXT_RESPONSE
);
}
return
false
;
}
// Abnormal cases in network side (see section 6.3.3.5 @3GPP TS 24.501)
if
(
sp
.
get
()
->
get_pdu_session_status
()
==
pdu_session_status_e
::
PDU_SESSION_INACTIVE_PENDING
)
{
// Ignore the message
Logger
::
smf_app
().
info
(
"A PDU Session Release Command has been sent for this session "
"(session ID %d), ignore the message!"
,
nas_msg
.
plain
.
sm
.
header
.
pdu_session_identity
);
return
false
;
}
// Message Type
//_5GSMCause
// presence
// ExtendedProtocolConfigurationOptions
Logger
::
smf_app
().
info
(
"PTI %d"
,
nas_msg
.
plain
.
sm
.
header
.
procedure_transaction_identity
);
procedure_transaction_id_t
pti
=
{
.
procedure_transaction_id
=
nas_msg
.
plain
.
sm
.
header
.
procedure_transaction_identity
};
sm_context_resp
.
get
()
->
res
.
set_pti
(
pti
);
if
(
nas_msg
.
plain
.
sm
.
pdu_session_modification_command_reject
.
_5gsmcause
==
static_cast
<
uint8_t
>
(
cause_value_5gsm_e
::
CAUSE_43_INVALID_PDU_SESSION_IDENTITY
))
{
// Update PDU Session status -> INACTIVE
sp
.
get
()
->
set_pdu_session_status
(
pdu_session_status_e
::
PDU_SESSION_INACTIVE
);
// TODO: Release locally the existing PDU Session (see
// section 6.3.2.5@3GPP TS 24.501)
}
else
if
(
sp
.
get
()
->
get_pdu_session_status
()
==
pdu_session_status_e
::
PDU_SESSION_MODIFICATION_PENDING
)
{
// Update PDU Session status -> ACTIVE
sp
.
get
()
->
set_pdu_session_status
(
pdu_session_status_e
::
PDU_SESSION_ACTIVE
);
}
// Message Type
// Presence
// 5GSM Cause
// Extended Protocol Configuration Options
// stop T3591
itti_inst
->
timer_remove
(
sp
.
get
()
->
timer_T3591
);
// Release the resources related to this PDU Session (in Procedure)
// don't need to create a procedure to update UPF
// get the associated QoS flows: to be used for PFCP Session
// Modification procedure
std
::
vector
<
smf_qos_flow
>
qos_flows
;
sp
.
get
()
->
get_qos_flows
(
qos_flows
);
for
(
auto
i
:
qos_flows
)
{
sm_context_request
.
get
()
->
req
.
add_qfi
(
i
.
qfi
.
qfi
);
}
return
true
;
}
bool
smf_context
::
handle_pdu_session_release_request
(
nas_message_t
&
nas_msg
,
std
::
shared_ptr
<
itti_n11_update_sm_context_request
>
&
sm_context_request
,
std
::
shared_ptr
<
itti_n11_update_sm_context_response
>
&
sm_context_resp
,
std
::
shared_ptr
<
smf_pdu_session
>
&
sp
)
{
std
::
string
n1_sm_msg
,
n1_sm_msg_hex
;
std
::
string
n2_sm_info
,
n2_sm_info_hex
;
sm_context_resp
.
get
()
->
session_procedure_type
=
session_management_procedures_type_e
::
PDU_SESSION_RELEASE_UE_REQUESTED_STEP1
;
// verify PDU Session ID
if
(
sm_context_request
.
get
()
->
req
.
get_pdu_session_id
()
!=
nas_msg
.
plain
.
sm
.
header
.
pdu_session_identity
)
{
// TODO: PDU Session ID mismatch
}
//-------------------------------------------------------------------------------------
bool
smf_context
::
handle_pdu_session_release_complete
(
nas_message_t
&
nas_msg
,
std
::
shared_ptr
<
itti_n11_update_sm_context_request
>&
sm_context_request
,
std
::
shared_ptr
<
itti_n11_update_sm_context_response
>&
sm_context_resp
,
std
::
shared_ptr
<
smf_pdu_session
>&
sp
)
{
sm_context_resp
.
get
()
->
session_procedure_type
=
session_management_procedures_type_e
::
PDU_SESSION_RELEASE_UE_REQUESTED_STEP3
;
// Abnormal cases in network side (see section 6.4.3.6 @3GPP TS 24.501)
if
(
sp
.
get
()
->
get_pdu_session_status
()
==
pdu_session_status_e
::
PDU_SESSION_INACTIVE
)
{
Logger
::
smf_app
().
warn
(
"PDU Session status: INACTIVE, send PDU Session Release Reject "
"to UE!"
);
if
(
smf_n1
::
get_instance
().
create_n1_pdu_session_release_reject
(
sm_context_request
.
get
()
->
req
,
n1_sm_msg
,
cause_value_5gsm_e
::
CAUSE_43_INVALID_PDU_SESSION_IDENTITY
))
{
smf_app_inst
->
convert_string_2_hex
(
n1_sm_msg
,
n1_sm_msg_hex
);
// trigger to send reply to AMF
smf_app_inst
->
trigger_update_context_error_response
(
http_status_code_e
::
HTTP_STATUS_CODE_403_FORBIDDEN
,
PDU_SESSION_APPLICATION_ERROR_NETWORK_FAILURE
,
n1_sm_msg_hex
,
sm_context_request
.
get
()
->
pid
);
}
else
{
smf_app_inst
->
trigger_http_response
(
http_status_code_e
::
HTTP_STATUS_CODE_500_INTERNAL_SERVER_ERROR
,
sm_context_request
.
get
()
->
pid
,
N11_SESSION_UPDATE_SM_CONTEXT_RESPONSE
);
}
return
false
;
}
// Abnormal cases in network side (see section 6.3.3.5 @3GPP TS 24.501)
if
(
sp
.
get
()
->
get_pdu_session_status
()
==
pdu_session_status_e
::
PDU_SESSION_INACTIVE_PENDING
)
{
// Ignore the message
Logger
::
smf_app
().
info
(
"A PDU Session Release Command has been sent for this session "
"(session ID %d), ignore the message!"
,
nas_msg
.
plain
.
sm
.
header
.
pdu_session_identity
);
return
false
;
}
// verify PDU Session ID
if
(
sm_context_request
.
get
()
->
req
.
get_pdu_session_id
()
!=
nas_msg
.
plain
.
sm
.
header
.
pdu_session_identity
)
{
// TODO: PDU Session ID mismatch
}
Logger
::
smf_app
().
info
(
"PTI %d"
,
nas_msg
.
plain
.
sm
.
header
.
procedure_transaction_identity
);
procedure_transaction_id_t
pti
=
{
.
procedure_transaction_id
=
nas_msg
.
plain
.
sm
.
header
.
procedure_transaction_identity
};
sm_context_resp
.
get
()
->
res
.
set_pti
(
pti
);
// Message Type
// Presence
// 5GSM Cause
// Extended Protocol Configuration Options
// Release the resources related to this PDU Session (in Procedure)
// get the associated QoS flows: to be used for PFCP Session
// Modification procedure
std
::
vector
<
smf_qos_flow
>
qos_flows
;
sp
.
get
()
->
get_qos_flows
(
qos_flows
);
for
(
auto
i
:
qos_flows
)
{
sm_context_request
.
get
()
->
req
.
add_qfi
(
i
.
qfi
.
qfi
);
}
Logger
::
smf_app
().
info
(
"PTI %d"
,
nas_msg
.
plain
.
sm
.
header
.
procedure_transaction_identity
);
procedure_transaction_id_t
pti
=
{
.
procedure_transaction_id
=
nas_msg
.
plain
.
sm
.
header
.
procedure_transaction_identity
};
if
(
nas_msg
.
plain
.
sm
.
header
.
message_type
!=
PDU_SESSION_RELEASE_COMPLETE
)
{
// TODO: Message Type mismatch
}
// 5GSM Cause
// Extended Protocol Configuration Options
// Update PDU Session status -> INACTIVE
sp
.
get
()
->
set_pdu_session_status
(
pdu_session_status_e
::
PDU_SESSION_INACTIVE
);
// Stop timer T3592
itti_inst
->
timer_remove
(
sp
.
get
()
->
timer_T3592
);
// TODO: SMF invokes Nsmf_PDUSession_SMContextStatusNotify to notify AMF
// that the SM context for this PDU Session is released
scid_t
scid
=
{};
try
{
scid
=
std
::
stoi
(
sm_context_request
.
get
()
->
scid
);
}
catch
(
const
std
::
exception
&
err
)
{
Logger
::
smf_app
().
warn
(
"Received a PDU Session Update SM Context Request, couldn't "
"retrieve the corresponding SMF context, ignore message!"
);
// TODO: return;
}
// need to update UPF accordingly
return
true
;
//update_upf = true;
}
bool
smf_context
::
handle_pdu_session_release_complete
(
nas_message_t
&
nas_msg
,
std
::
shared_ptr
<
itti_n11_update_sm_context_request
>
&
sm_context_request
,
std
::
shared_ptr
<
itti_n11_update_sm_context_response
>
&
sm_context_resp
,
std
::
shared_ptr
<
smf_pdu_session
>
&
sp
)
{
sm_context_resp
.
get
()
->
session_procedure_type
=
session_management_procedures_type_e
::
PDU_SESSION_RELEASE_UE_REQUESTED_STEP3
;
// verify PDU Session ID
if
(
sm_context_request
.
get
()
->
req
.
get_pdu_session_id
()
!=
nas_msg
.
plain
.
sm
.
header
.
pdu_session_identity
)
{
// TODO: PDU Session ID mismatch
}
Logger
::
smf_app
().
info
(
"PTI %d"
,
nas_msg
.
plain
.
sm
.
header
.
procedure_transaction_identity
);
procedure_transaction_id_t
pti
=
{
.
procedure_transaction_id
=
nas_msg
.
plain
.
sm
.
header
.
procedure_transaction_identity
};
if
(
nas_msg
.
plain
.
sm
.
header
.
message_type
!=
PDU_SESSION_RELEASE_COMPLETE
)
{
// TODO: Message Type mismatch
}
// 5GSM Cause
// Extended Protocol Configuration Options
// Update PDU Session status -> INACTIVE
sp
.
get
()
->
set_pdu_session_status
(
pdu_session_status_e
::
PDU_SESSION_INACTIVE
);
// Stop timer T3592
itti_inst
->
timer_remove
(
sp
.
get
()
->
timer_T3592
);
// don't need to create a procedure to update UPF
// TODO: SMF invokes Nsmf_PDUSession_SMContextStatusNotify to notify AMF
// that the SM context for this PDU Session is released
scid_t
scid
=
{};
try
{
scid
=
std
::
stoi
(
sm_context_request
.
get
()
->
scid
);
}
catch
(
const
std
::
exception
&
err
)
{
Logger
::
smf_app
().
warn
(
"Received a PDU Session Update SM Context Request, couldn't "
"retrieve the corresponding SMF context, ignore message!"
);
// TODO: return;
}
event_sub
.
sm_context_status
(
scid
,
static_cast
<
uint32_t
>
(
sm_context_status_e
::
SM_CONTEXT_STATUS_RELEASED
),
sm_context_request
.
get
()
->
http_version
);
// Get SUPI
supi64_t
supi64
=
smf_supi_to_u64
(
sm_context_request
.
get
()
->
req
.
get_supi
());
// Trigger PDU Session Release event notification
event_sub
.
ee_pdu_session_release
(
supi64
,
sm_context_request
.
get
()
->
req
.
get_pdu_session_id
(),
sm_context_request
.
get
()
->
http_version
);
// TODO: if dynamic PCC applied, SMF invokes an SM Policy Association
// Termination
// TODO: SMF unsubscribes from Session Management Subscription data
// changes notification from UDM by invoking Numd_SDM_Unsubscribe
//TODO: should check if sd context exist
std
::
shared_ptr
<
dnn_context
>
sd
=
{};
find_dnn_context
(
sm_context_request
.
get
()
->
req
.
get_snssai
(),
sm_context_request
.
get
()
->
req
.
get_dnn
(),
sd
);
if
(
sd
.
get
()
!=
nullptr
)
{
if
(
sd
.
get
()
->
get_number_pdu_sessions
()
==
0
)
{
Logger
::
smf_app
().
debug
(
"Unsubscribe from Session Management Subscription data changes "
"notification from UDM"
);
// TODO: unsubscribes from Session Management Subscription data
// changes notification from UDM
}
}
// TODO: Invoke Nudm_UECM_Deregistration
}
bool
smf_context
::
handle_pdu_session_resource_setup_response_transfer
(
std
::
string
&
n2_sm_information
,
std
::
shared_ptr
<
itti_n11_update_sm_context_request
>
&
sm_context_request
)
{
std
::
string
n1_sm_msg
,
n1_sm_msg_hex
;
std
::
string
n2_sm_info
,
n2_sm_info_hex
;
/* if (sm_context_request.get()->req.rat_type_is_set() and
sm_context_request.get()->req.an_type_is_set()) {
procedure_type = session_management_procedures_type_e::
SERVICE_REQUEST_UE_TRIGGERED_STEP2;
Logger::smf_app().info(
"UE-Triggered Service Request, processing N2 SM Information");
} else {
procedure_type = session_management_procedures_type_e::
PDU_SESSION_ESTABLISHMENT_UE_REQUESTED;
Logger::smf_app().info(
"PDU Session Establishment Request, processing N2 SM "
"Information");
}
*/
// Ngap_PDUSessionResourceSetupResponseTransfer
std
::
shared_ptr
<
Ngap_PDUSessionResourceSetupResponseTransfer_t
>
decoded_msg
=
std
::
make_shared
<
Ngap_PDUSessionResourceSetupResponseTransfer_t
>
();
int
decode_status
=
smf_n2
::
get_instance
().
decode_n2_sm_information
(
decoded_msg
,
n2_sm_information
);
if
(
decode_status
==
RETURNerror
)
{
// error, send error to AMF
Logger
::
smf_app
().
warn
(
"Decode N2 SM (Ngap_PDUSessionResourceSetupResponseTransfer) "
"failed!"
);
// PDU Session Establishment Reject
// 24.501: response with a 5GSM STATUS message including cause "#95
// Semantically incorrect message"
if
(
smf_n1
::
get_instance
().
create_n1_pdu_session_establishment_reject
(
sm_context_request
.
get
()
->
req
,
n1_sm_msg
,
cause_value_5gsm_e
::
CAUSE_95_SEMANTICALLY_INCORRECT_MESSAGE
))
{
smf_app_inst
->
convert_string_2_hex
(
n1_sm_msg
,
n1_sm_msg_hex
);
// TODO: need N1SM?
// trigger to send reply to AMF
smf_app_inst
->
trigger_update_context_error_response
(
http_status_code_e
::
HTTP_STATUS_CODE_403_FORBIDDEN
,
PDU_SESSION_APPLICATION_ERROR_N2_SM_ERROR
,
sm_context_request
.
get
()
->
pid
);
event_sub
.
sm_context_status
(
scid
,
static_cast
<
uint32_t
>
(
sm_context_status_e
::
SM_CONTEXT_STATUS_RELEASED
),
sm_context_request
.
get
()
->
http_version
);
}
else
{
smf_app_inst
->
trigger_http_response
(
http_status_code_e
::
HTTP_STATUS_CODE_500_INTERNAL_SERVER_ERROR
,
sm_context_request
.
get
()
->
pid
,
N11_SESSION_UPDATE_SM_CONTEXT_RESPONSE
);
}
return
false
;
}
// Get SUPI
supi64_t
supi64
=
smf_supi_to_u64
(
sm_context_request
.
get
()
->
req
.
get_supi
());
// Trigger PDU Session Release event notification
event_sub
.
ee_pdu_session_release
(
supi64
,
sm_context_request
.
get
()
->
req
.
get_pdu_session_id
(),
sm_context_request
.
get
()
->
http_version
);
// store AN Tunnel Info + list of accepted QFIs
pfcp
::
fteid_t
dl_teid
=
{};
memcpy
(
&
dl_teid
.
teid
,
decoded_msg
->
dLQosFlowPerTNLInformation
.
uPTransportLayerInformation
.
choice
.
gTPTunnel
->
gTP_TEID
.
buf
,
TEID_GRE_KEY_LENGTH
);
memcpy
(
&
dl_teid
.
ipv4_address
,
decoded_msg
->
dLQosFlowPerTNLInformation
.
uPTransportLayerInformation
.
choice
.
gTPTunnel
->
transportLayerAddress
.
buf
,
4
);
dl_teid
.
teid
=
ntohl
(
dl_teid
.
teid
);
dl_teid
.
v4
=
1
;
// Only V4 for now
sm_context_request
.
get
()
->
req
.
set_dl_fteid
(
dl_teid
);
// TODO: if dynamic PCC applied, SMF invokes an SM Policy Association
// Termination
// TODO: SMF unsubscribes from Session Management Subscription data
// changes notification from UDM by invoking Numd_SDM_Unsubscribe
Logger
::
smf_app
().
debug
(
"DL GTP F-TEID (AN F-TEID) "
"0x%"
PRIx32
" "
,
dl_teid
.
teid
);
Logger
::
smf_app
().
debug
(
"uPTransportLayerInformation (AN IP Addr) %s"
,
conv
::
toString
(
dl_teid
.
ipv4_address
).
c_str
());
// TODO: should check if sd context exist
std
::
shared_ptr
<
dnn_context
>
sd
=
{};
find_dnn_context
(
sm_context_request
.
get
()
->
req
.
get_snssai
(),
sm_context_request
.
get
()
->
req
.
get_dnn
(),
sd
);
for
(
int
i
=
0
;
i
<
decoded_msg
->
dLQosFlowPerTNLInformation
.
associatedQosFlowList
.
list
.
count
;
i
++
)
{
pfcp
::
qfi_t
qfi
((
uint8_t
)(
decoded_msg
->
dLQosFlowPerTNLInformation
.
associatedQosFlowList
.
list
.
array
[
i
])
->
qosFlowIdentifier
);
sm_context_request
.
get
()
->
req
.
add_qfi
(
qfi
);
if
(
sd
.
get
()
!=
nullptr
)
{
if
(
sd
.
get
()
->
get_number_pdu_sessions
()
==
0
)
{
Logger
::
smf_app
().
debug
(
"
QoSFlowPerTNLInformation, AssociatedQosFlowList, QFI %d"
,
(
decoded_msg
->
dLQosFlowPerTNLInformation
.
associatedQosFlowList
.
list
.
array
[
i
])
->
qosFlowIdentifier
);
"
Unsubscribe from Session Management Subscription data changes "
"notification from UDM"
);
// TODO: unsubscribes from Session Management Subscription data
// changes notification from UDM
}
return
true
;
}
// TODO: Invoke Nudm_UECM_Deregistration
return
true
;
}
bool
smf_context
::
handle_pdu_session_resource_setup_unsuccessful_transfer
(
std
::
string
&
n2_sm_information
,
std
::
shared_ptr
<
itti_n11_update_sm_context_request
>
&
sm_context_request
)
{
std
::
string
n1_sm_msg
,
n1_sm_msg_hex
;
// std::string n2_sm_info, n2_sm_info_hex;
// Ngap_PDUSessionResourceSetupUnsuccessfulTransfer
std
::
shared_ptr
<
Ngap_PDUSessionResourceSetupUnsuccessfulTransfer_t
>
decoded_msg
=
std
::
make_shared
<
Ngap_PDUSessionResourceSetupUnsuccessfulTransfer_t
>
();
int
decode_status
=
smf_n2
::
get_instance
().
decode_n2_sm_information
(
decoded_msg
,
n2_sm_information
);
if
(
decode_status
==
RETURNerror
)
{
Logger
::
smf_app
().
warn
(
"Decode N2 SM (Ngap_PDUSessionResourceSetupUnsuccessfulTransfer) "
"failed!"
);
// trigger to send reply to AMF
smf_app_inst
->
trigger_update_context_error_response
(
http_status_code_e
::
HTTP_STATUS_CODE_403_FORBIDDEN
,
PDU_SESSION_APPLICATION_ERROR_N2_SM_ERROR
,
sm_context_request
.
get
()
->
pid
);
return
false
;
}
//-------------------------------------------------------------------------------------
bool
smf_context
::
handle_pdu_session_resource_setup_response_transfer
(
std
::
string
&
n2_sm_information
,
std
::
shared_ptr
<
itti_n11_update_sm_context_request
>&
sm_context_request
)
{
std
::
string
n1_sm_msg
,
n1_sm_msg_hex
;
// Logger::smf_app().info("PDU Session Resource Setup Unsuccessful
// Transfer cause %d",decoded_msg->cause ); PDU Session Establishment
// Reject, 24.501 cause "#26 Insufficient resources"
// Ngap_PDUSessionResourceSetupResponseTransfer
std
::
shared_ptr
<
Ngap_PDUSessionResourceSetupResponseTransfer_t
>
decoded_msg
=
std
::
make_shared
<
Ngap_PDUSessionResourceSetupResponseTransfer_t
>
();
int
decode_status
=
smf_n2
::
get_instance
().
decode_n2_sm_information
(
decoded_msg
,
n2_sm_information
);
if
(
decode_status
==
RETURNerror
)
{
// error, send error to AMF
Logger
::
smf_app
().
warn
(
"Decode N2 SM (Ngap_PDUSessionResourceSetupResponseTransfer) "
"failed!"
);
// PDU Session Establishment Reject
// 24.501: response with a 5GSM STATUS message including cause "#95
// Semantically incorrect message"
if
(
smf_n1
::
get_instance
().
create_n1_pdu_session_establishment_reject
(
sm_context_request
.
get
()
->
req
,
n1_sm_msg
,
cause_value_5gsm_e
::
CAUSE_
26_INSUFFICIENT_RESOURCES
))
{
sm_context_request
.
get
()
->
req
,
n1_sm_msg
,
cause_value_5gsm_e
::
CAUSE_
95_SEMANTICALLY_INCORRECT_MESSAGE
))
{
smf_app_inst
->
convert_string_2_hex
(
n1_sm_msg
,
n1_sm_msg_hex
);
// trigger to send reply to AMF
smf_app_inst
->
trigger_update_context_error_response
(
http_status_code_e
::
HTTP_STATUS_CODE_403_FORBIDDEN
,
PDU_SESSION_APPLICATION_ERROR_
UE_NOT_RESPONDING
,
n1_sm_msg_hex
,
sm_context_request
.
get
()
->
pid
);
PDU_SESSION_APPLICATION_ERROR_
N2_SM_ERROR
,
sm_context_request
.
get
()
->
pid
);
// TODO: Need release established resources?
}
else
{
smf_app_inst
->
trigger_http_response
(
http_status_code_e
::
HTTP_STATUS_CODE_500_INTERNAL_SERVER_ERROR
,
sm_context_request
.
get
()
->
pid
,
N11_SESSION_UPDATE_SM_CONTEXT_RESPONSE
);
sm_context_request
.
get
()
->
pid
,
N11_SESSION_UPDATE_SM_CONTEXT_RESPONSE
);
}
return
true
;
}
bool
smf_context
::
handle_pdu_session_resource_modify_response_transfer
(
std
::
string
&
n2_sm_information
,
std
::
shared_ptr
<
itti_n11_update_sm_context_request
>
&
sm_context_request
)
{
std
::
string
n1_sm_msg
,
n1_sm_msg_hex
;
// Ngap_PDUSessionResourceModifyResponseTransfer
std
::
shared_ptr
<
Ngap_PDUSessionResourceModifyResponseTransfer_t
>
decoded_msg
=
std
::
make_shared
<
Ngap_PDUSessionResourceModifyResponseTransfer_t
>
();
int
decode_status
=
smf_n2
::
get_instance
().
decode_n2_sm_information
(
decoded_msg
,
n2_sm_information
);
if
(
decode_status
==
RETURNerror
)
{
Logger
::
smf_app
().
warn
(
"Decode N2 SM (Ngap_PDUSessionResourceModifyResponseTransfer) "
"failed!"
);
// trigger to send reply to AMF
smf_app_inst
->
trigger_update_context_error_response
(
http_status_code_e
::
HTTP_STATUS_CODE_403_FORBIDDEN
,
PDU_SESSION_APPLICATION_ERROR_N2_SM_ERROR
,
sm_context_request
.
get
()
->
pid
);
return
false
;
}
// see section 8.2.3 (PDU Session Resource Modify) @3GPP TS 38.413
// if dL_NGU_UP_TNLInformation is included, it shall be considered as
// the new DL transport layer addr for the PDU session (should be
// verified)
// TODO: may include uL_NGU_UP_TNLInformation (mapping between each new
// DL transport layer address and the corresponding UL transport layer
// address)
pfcp
::
fteid_t
dl_teid
;
memcpy
(
&
dl_teid
.
teid
,
decoded_msg
->
dL_NGU_UP_TNLInformation
->
choice
.
gTPTunnel
->
gTP_TEID
.
buf
,
TEID_GRE_KEY_LENGTH
);
memcpy
(
&
dl_teid
.
ipv4_address
,
decoded_msg
->
dL_NGU_UP_TNLInformation
->
choice
.
gTPTunnel
->
transportLayerAddress
.
buf
,
4
);
dl_teid
.
teid
=
ntohl
(
dl_teid
.
teid
);
dl_teid
.
v4
=
1
;
// Only v4 for now
sm_context_request
.
get
()
->
req
.
set_dl_fteid
(
dl_teid
);
// list of Qos Flows which have been successfully setup or modified
if
(
decoded_msg
->
qosFlowAddOrModifyResponseList
)
{
for
(
int
i
=
0
;
i
<
decoded_msg
->
qosFlowAddOrModifyResponseList
->
list
.
count
;
i
++
)
{
sm_context_request
.
get
()
->
req
.
add_qfi
(
(
decoded_msg
->
qosFlowAddOrModifyResponseList
->
list
.
array
[
i
])
->
qosFlowIdentifier
);
}
}
// TODO: list of QoS Flows which have failed to be modified,
// qosFlowFailedToAddOrModifyList
// TODO: additionalDLQosFlowPerTNLInformation
return
false
;
}
// store AN Tunnel Info + list of accepted QFIs
pfcp
::
fteid_t
dl_teid
=
{};
memcpy
(
&
dl_teid
.
teid
,
decoded_msg
->
dLQosFlowPerTNLInformation
.
uPTransportLayerInformation
.
choice
.
gTPTunnel
->
gTP_TEID
.
buf
,
TEID_GRE_KEY_LENGTH
);
memcpy
(
&
dl_teid
.
ipv4_address
,
decoded_msg
->
dLQosFlowPerTNLInformation
.
uPTransportLayerInformation
.
choice
.
gTPTunnel
->
transportLayerAddress
.
buf
,
4
);
dl_teid
.
teid
=
ntohl
(
dl_teid
.
teid
);
dl_teid
.
v4
=
1
;
// Only V4 for now
sm_context_request
.
get
()
->
req
.
set_dl_fteid
(
dl_teid
);
Logger
::
smf_app
().
debug
(
"DL GTP F-TEID (AN F-TEID) "
"0x%"
PRIx32
" "
,
dl_teid
.
teid
);
Logger
::
smf_app
().
debug
(
"uPTransportLayerInformation (AN IP Addr) %s"
,
conv
::
toString
(
dl_teid
.
ipv4_address
).
c_str
());
for
(
int
i
=
0
;
i
<
decoded_msg
->
dLQosFlowPerTNLInformation
.
associatedQosFlowList
.
list
.
count
;
i
++
)
{
pfcp
::
qfi_t
qfi
((
uint8_t
)(
decoded_msg
->
dLQosFlowPerTNLInformation
.
associatedQosFlowList
.
list
.
array
[
i
])
->
qosFlowIdentifier
);
sm_context_request
.
get
()
->
req
.
add_qfi
(
qfi
);
Logger
::
smf_app
().
debug
(
"QoSFlowPerTNLInformation, AssociatedQosFlowList, QFI %d"
,
(
decoded_msg
->
dLQosFlowPerTNLInformation
.
associatedQosFlowList
.
list
.
array
[
i
])
->
qosFlowIdentifier
);
}
return
true
;
}
bool
smf_context
::
handle_pdu_session_resource_release_response_transfer
(
std
::
string
&
n2_sm_information
,
std
::
shared_ptr
<
itti_n11_update_sm_context_request
>
&
sm_context_request
)
{
//-------------------------------------------------------------------------------------
bool
smf_context
::
handle_pdu_session_resource_setup_unsuccessful_transfer
(
std
::
string
&
n2_sm_information
,
std
::
shared_ptr
<
itti_n11_update_sm_context_request
>&
sm_context_request
)
{
std
::
string
n1_sm_msg
,
n1_sm_msg_hex
;
std
::
string
n1_sm_msg
,
n1_sm_msg_hex
;
// Ngap_PDUSessionResourceSetupUnsuccessfulTransfer
std
::
shared_ptr
<
Ngap_PDUSessionResourceSetupUnsuccessfulTransfer_t
>
decoded_msg
=
std
::
make_shared
<
Ngap_PDUSessionResourceSetupUnsuccessfulTransfer_t
>
();
int
decode_status
=
smf_n2
::
get_instance
().
decode_n2_sm_information
(
decoded_msg
,
n2_sm_information
);
// TODO: SMF does nothing (Step 7, section 4.3.4.2@3GPP TS 23.502)
// Ngap_PDUSessionResourceReleaseResponseTransfer
std
::
shared_ptr
<
Ngap_PDUSessionResourceReleaseResponseTransfer_t
>
decoded_msg
=
std
::
make_shared
<
Ngap_PDUSessionResourceReleaseResponseTransfer_t
>
();
int
decode_status
=
smf_n2
::
get_instance
().
decode_n2_sm_information
(
decoded_msg
,
n2_sm_information
);
if
(
decode_status
==
RETURNerror
)
{
Logger
::
smf_app
().
warn
(
"Decode N2 SM (Ngap_PDUSessionResourceReleaseResponseTransfer) "
"failed!"
);
// trigger to send reply to AMF
smf_app_inst
->
trigger_update_context_error_response
(
http_status_code_e
::
HTTP_STATUS_CODE_403_FORBIDDEN
,
PDU_SESSION_APPLICATION_ERROR_N2_SM_ERROR
,
sm_context_request
.
get
()
->
pid
);
if
(
decode_status
==
RETURNerror
)
{
Logger
::
smf_app
().
warn
(
"Decode N2 SM (Ngap_PDUSessionResourceSetupUnsuccessfulTransfer) "
"failed!"
);
// trigger to send reply to AMF
smf_app_inst
->
trigger_update_context_error_response
(
http_status_code_e
::
HTTP_STATUS_CODE_403_FORBIDDEN
,
PDU_SESSION_APPLICATION_ERROR_N2_SM_ERROR
,
sm_context_request
.
get
()
->
pid
);
return
false
;
}
return
false
;
}
// PDU Session Establishment Reject, 24.501 cause "#26 Insufficient resources"
if
(
smf_n1
::
get_instance
().
create_n1_pdu_session_establishment_reject
(
sm_context_request
.
get
()
->
req
,
n1_sm_msg
,
cause_value_5gsm_e
::
CAUSE_26_INSUFFICIENT_RESOURCES
))
{
smf_app_inst
->
convert_string_2_hex
(
n1_sm_msg
,
n1_sm_msg_hex
);
// trigger to send reply to AMF
smf_app_inst
->
trigger_update_context_error_response
(
http_status_code_e
::
HTTP_STATUS_CODE_403_FORBIDDEN
,
PDU_SESSION_APPLICATION_ERROR_UE_NOT_RESPONDING
,
n1_sm_msg_hex
,
sm_context_request
.
get
()
->
pid
);
// don't need to create a procedure to update UPF
// TODO: Need release established resources?
}
else
{
smf_app_inst
->
trigger_http_response
(
http_status_code_e
::
HTTP_STATUS_CODE_200_OK
,
sm_context_request
.
get
()
->
pid
,
N11_SESSION_UPDATE_SM_CONTEXT_RESPONSE
);
http_status_code_e
::
HTTP_STATUS_CODE_500_INTERNAL_SERVER_ERROR
,
sm_context_request
.
get
()
->
pid
,
N11_SESSION_UPDATE_SM_CONTEXT_RESPONSE
);
}
return
true
;
}
//-------------------------------------------------------------------------------------
bool
smf_context
::
handle_pdu_session_resource_modify_response_transfer
(
std
::
string
&
n2_sm_information
,
std
::
shared_ptr
<
itti_n11_update_sm_context_request
>&
sm_context_request
)
{
std
::
string
n1_sm_msg
,
n1_sm_msg_hex
;
// Ngap_PDUSessionResourceModifyResponseTransfer
std
::
shared_ptr
<
Ngap_PDUSessionResourceModifyResponseTransfer_t
>
decoded_msg
=
std
::
make_shared
<
Ngap_PDUSessionResourceModifyResponseTransfer_t
>
();
int
decode_status
=
smf_n2
::
get_instance
().
decode_n2_sm_information
(
decoded_msg
,
n2_sm_information
);
if
(
decode_status
==
RETURNerror
)
{
Logger
::
smf_app
().
warn
(
"Decode N2 SM (Ngap_PDUSessionResourceModifyResponseTransfer) "
"failed!"
);
// trigger to send reply to AMF
smf_app_inst
->
trigger_update_context_error_response
(
http_status_code_e
::
HTTP_STATUS_CODE_403_FORBIDDEN
,
PDU_SESSION_APPLICATION_ERROR_N2_SM_ERROR
,
sm_context_request
.
get
()
->
pid
);
return
false
;
}
// see section 8.2.3 (PDU Session Resource Modify) @3GPP TS 38.413
// if dL_NGU_UP_TNLInformation is included, it shall be considered as
// the new DL transport layer addr for the PDU session (should be
// verified)
// TODO: may include uL_NGU_UP_TNLInformation (mapping between each new
// DL transport layer address and the corresponding UL transport layer
// address)
pfcp
::
fteid_t
dl_teid
;
memcpy
(
&
dl_teid
.
teid
,
decoded_msg
->
dL_NGU_UP_TNLInformation
->
choice
.
gTPTunnel
->
gTP_TEID
.
buf
,
TEID_GRE_KEY_LENGTH
);
memcpy
(
&
dl_teid
.
ipv4_address
,
decoded_msg
->
dL_NGU_UP_TNLInformation
->
choice
.
gTPTunnel
->
transportLayerAddress
.
buf
,
4
);
dl_teid
.
teid
=
ntohl
(
dl_teid
.
teid
);
dl_teid
.
v4
=
1
;
// Only v4 for now
sm_context_request
.
get
()
->
req
.
set_dl_fteid
(
dl_teid
);
// list of Qos Flows which have been successfully setup or modified
if
(
decoded_msg
->
qosFlowAddOrModifyResponseList
)
{
for
(
int
i
=
0
;
i
<
decoded_msg
->
qosFlowAddOrModifyResponseList
->
list
.
count
;
i
++
)
{
sm_context_request
.
get
()
->
req
.
add_qfi
(
(
decoded_msg
->
qosFlowAddOrModifyResponseList
->
list
.
array
[
i
])
->
qosFlowIdentifier
);
}
}
// TODO: list of QoS Flows which have failed to be modified,
// qosFlowFailedToAddOrModifyList
// TODO: additionalDLQosFlowPerTNLInformation
return
true
;
}
//-------------------------------------------------------------------------------------
bool
smf_context
::
handle_pdu_session_resource_release_response_transfer
(
std
::
string
&
n2_sm_information
,
std
::
shared_ptr
<
itti_n11_update_sm_context_request
>&
sm_context_request
)
{
std
::
string
n1_sm_msg
,
n1_sm_msg_hex
;
// TODO: SMF does nothing (Step 7, section 4.3.4.2@3GPP TS 23.502)
// Ngap_PDUSessionResourceReleaseResponseTransfer
std
::
shared_ptr
<
Ngap_PDUSessionResourceReleaseResponseTransfer_t
>
decoded_msg
=
std
::
make_shared
<
Ngap_PDUSessionResourceReleaseResponseTransfer_t
>
();
int
decode_status
=
smf_n2
::
get_instance
().
decode_n2_sm_information
(
decoded_msg
,
n2_sm_information
);
if
(
decode_status
==
RETURNerror
)
{
Logger
::
smf_app
().
warn
(
"Decode N2 SM (Ngap_PDUSessionResourceReleaseResponseTransfer) "
"failed!"
);
// trigger to send reply to AMF
smf_app_inst
->
trigger_update_context_error_response
(
http_status_code_e
::
HTTP_STATUS_CODE_403_FORBIDDEN
,
PDU_SESSION_APPLICATION_ERROR_N2_SM_ERROR
,
sm_context_request
.
get
()
->
pid
);
return
false
;
}
smf_app_inst
->
trigger_http_response
(
http_status_code_e
::
HTTP_STATUS_CODE_200_OK
,
sm_context_request
.
get
()
->
pid
,
N11_SESSION_UPDATE_SM_CONTEXT_RESPONSE
);
return
true
;
}
//-------------------------------------------------------------------------------------
bool
smf_context
::
handle_service_request
(
std
::
string
&
n2_sm_information
,
std
::
string
&
n2_sm_information
,
std
::
shared_ptr
<
itti_n11_update_sm_context_request
>&
sm_context_request
,
std
::
shared_ptr
<
itti_n11_update_sm_context_response
>&
sm_context_resp
,
std
::
shared_ptr
<
smf_pdu_session
>&
sp
)
{
std
::
string
n2_sm_info
,
n2_sm_info_hex
;
// std::string n1_sm_msg, n1_sm_msg_hex;
std
::
string
n2_sm_info
,
n2_sm_info_hex
;
// Update upCnxState
sp
.
get
()
->
set_upCnx_state
(
upCnx_state_e
::
UPCNX_STATE_ACTIVATING
)
;
// Update upCnxState
sp
.
get
()
->
set_upCnx_state
(
upCnx_state_e
::
UPCNX_STATE_ACTIVATING
);
// get QFIs associated with PDU session ID
std
::
vector
<
smf_qos_flow
>
qos_flows
=
{};
sp
.
get
()
->
get_qos_flows
(
qos_flows
);
for
(
auto
i
:
qos_flows
)
{
sm_context_request
.
get
()
->
req
.
add_qfi
(
i
.
qfi
.
qfi
);
// get QFIs associated with PDU session ID
std
::
vector
<
smf_qos_flow
>
qos_flows
=
{};
sp
.
get
()
->
get_qos_flows
(
qos_flows
);
for
(
auto
i
:
qos_flows
)
{
sm_context_request
.
get
()
->
req
.
add_qfi
(
i
.
qfi
.
qfi
);
qos_flow_context_updated
qcu
=
{};
qcu
.
set_cause
(
REQUEST_ACCEPTED
);
qcu
.
set_qfi
(
i
.
qfi
);
qcu
.
set_ul_fteid
(
i
.
ul_fteid
);
qcu
.
set_qos_profile
(
i
.
qos_profile
);
sm_context_resp
.
get
()
->
res
.
add_qos_flow_context_updated
(
qcu
);
}
qos_flow_context_updated
qcu
=
{};
qcu
.
set_cause
(
REQUEST_ACCEPTED
);
qcu
.
set_qfi
(
i
.
qfi
);
qcu
.
set_ul_fteid
(
i
.
ul_fteid
);
qcu
.
set_qos_profile
(
i
.
qos_profile
);
sm_context_resp
.
get
()
->
res
.
add_qos_flow_context_updated
(
qcu
);
}
sm_context_resp
.
get
()
->
session_procedure_type
=
session_management_procedures_type_e
::
SERVICE_REQUEST_UE_TRIGGERED_STEP1
;
// Create N2 SM Information: PDU Session Resource Setup Request Transfer IE
// N2 SM Information
smf_n2
::
get_instance
().
create_n2_pdu_session_resource_setup_request_transfer
(
sm_context_resp
.
get
()
->
res
,
n2_sm_info_type_e
::
PDU_RES_SETUP_REQ
,
n2_sm_info
);
sm_context_resp
.
get
()
->
session_procedure_type
=
session_management_procedures_type_e
::
SERVICE_REQUEST_UE_TRIGGERED_STEP1
;
// Create N2 SM Information: PDU Session Resource Setup Request Transfer IE
// N2 SM Information
smf_n2
::
get_instance
()
.
create_n2_pdu_session_resource_setup_request_transfer
(
sm_context_resp
.
get
()
->
res
,
n2_sm_info_type_e
::
PDU_RES_SETUP_REQ
,
n2_sm_info
);
smf_app_inst
->
convert_string_2_hex
(
n2_sm_info
,
n2_sm_info_hex
);
sm_context_resp
.
get
()
->
res
.
set_n2_sm_information
(
n2_sm_info_hex
);
// fill the content of SmContextUpdatedData
nlohmann
::
json
json_data
=
{};
json_data
[
"n2InfoContainer"
][
"n2InformationClass"
]
=
N1N2_MESSAGE_CLASS
;
json_data
[
"n2InfoContainer"
][
"smInfo"
][
"PduSessionId"
]
=
sm_context_resp
.
get
()
->
res
.
get_pdu_session_id
();
json_data
[
"n2InfoContainer"
][
"smInfo"
][
"n2InfoContent"
][
"ngapData"
]
[
"contentId"
]
=
N2_SM_CONTENT_ID
;
json_data
[
"n2InfoContainer"
][
"smInfo"
][
"n2InfoContent"
][
"ngapIeType"
]
=
"PDU_RES_SETUP_REQ"
;
// NGAP message
json_data
[
"upCnxState"
]
=
"ACTIVATING"
;
sm_context_resp
.
get
()
->
res
.
set_json_data
(
json_data
);
// Update upCnxState to ACTIVATING
sp
.
get
()
->
set_upCnx_state
(
upCnx_state_e
::
UPCNX_STATE_ACTIVATING
);
// TODO: If new UPF is used, need to send N4 Session Modification
// Request/Response to new/old UPF
// Accept the activation of UP connection and continue to using the current
// UPF
// TODO: Accept the activation of UP connection and select a new UPF
// Reject the activation of UP connection
// SMF fails to find a suitable I-UPF: i) trigger re-establishment of PDU
// Session; or ii) keep PDU session but reject the activation of UP
// connection; or iii) release PDU session
smf_app_inst
->
convert_string_2_hex
(
n2_sm_info
,
n2_sm_info_hex
);
sm_context_resp
.
get
()
->
res
.
set_n2_sm_information
(
n2_sm_info_hex
);
// fill the content of SmContextUpdatedData
nlohmann
::
json
json_data
=
{};
json_data
[
"n2InfoContainer"
][
"n2InformationClass"
]
=
N1N2_MESSAGE_CLASS
;
json_data
[
"n2InfoContainer"
][
"smInfo"
][
"PduSessionId"
]
=
sm_context_resp
.
get
()
->
res
.
get_pdu_session_id
();
json_data
[
"n2InfoContainer"
][
"smInfo"
][
"n2InfoContent"
][
"ngapData"
]
[
"contentId"
]
=
N2_SM_CONTENT_ID
;
json_data
[
"n2InfoContainer"
][
"smInfo"
][
"n2InfoContent"
][
"ngapIeType"
]
=
"PDU_RES_SETUP_REQ"
;
// NGAP message
json_data
[
"upCnxState"
]
=
"ACTIVATING"
;
sm_context_resp
.
get
()
->
res
.
set_json_data
(
json_data
);
// Update upCnxState to ACTIVATING
sp
.
get
()
->
set_upCnx_state
(
upCnx_state_e
::
UPCNX_STATE_ACTIVATING
);
// TODO: If new UPF is used, need to send N4 Session Modification
// Request/Response to new/old UPF
// Accept the activation of UP connection and continue to using the current
// UPF
// TODO: Accept the activation of UP connection and select a new UPF
// Reject the activation of UP connection
// SMF fails to find a suitable I-UPF: i) trigger re-establishment of PDU
// Session; or ii) keep PDU session but reject the activation of UP
// connection; or iii) release PDU session
return
true
;
}
//-------------------------------------------------------------------------------------
void
smf_context
::
handle_pdu_session_update_sm_context_request
(
std
::
shared_ptr
<
itti_n11_update_sm_context_request
>
smreq
)
{
...
...
@@ -2271,7 +2252,8 @@ void smf_context::handle_pdu_session_update_sm_context_request(
sp
.
get
()
->
get_pdu_session_type
().
pdu_session_type
);
// Assign necessary information for the response
xgpp_conv
::
update_sm_context_response_from_ct_request
(
smreq
,
sm_context_resp_pending
);
xgpp_conv
::
update_sm_context_response_from_ct_request
(
smreq
,
sm_context_resp_pending
);
// Step 2.1. Decode N1 (if content is available)
if
(
sm_context_req_msg
.
n1_sm_msg_is_set
())
{
...
...
@@ -2295,318 +2277,67 @@ void smf_context::handle_pdu_session_update_sm_context_request(
uint8_t
message_type
=
decoded_nas_msg
.
plain
.
sm
.
header
.
message_type
;
switch
(
message_type
)
{
case
PDU_SESSION_MODIFICATION_REQUEST
:
{
// PDU Session Modification procedure (UE-initiated, step 1.a,
// Section 4.3.3.2@3GPP TS 23.502) UE initiated PDU session
// modification request (Step 1)
Logger
::
smf_app
().
debug
(
"PDU_SESSION_MODIFICATION_REQUEST"
);
procedure_type
=
session_management_procedures_type_e
::
PDU_SESSION_MODIFICATION_UE_INITIATED_STEP1
;
if
(
!
handle_pdu_session_modification_request
(
decoded_nas_msg
,
smreq
,
sm_context_resp_pending
,
sp
))
return
;
/*
sm_context_resp_pending->session_procedure_type =
session_management_procedures_type_e::
PDU_SESSION_MODIFICATION_UE_INITIATED_STEP1;
// check if the PDU Session Release Command is already sent for this
// message (see section 6.3.3.5 @3GPP TS 24.501)
if (sp.get()->get_pdu_session_status() ==
pdu_session_status_e::PDU_SESSION_INACTIVE_PENDING) {
// Ignore the message
Logger::smf_app().info(
"A PDU Session Release Command has been sent for this session "
"(session ID %d), ignore the message!",
decoded_nas_msg.plain.sm.header.pdu_session_identity);
if
(
!
handle_pdu_session_modification_request
(
decoded_nas_msg
,
smreq
,
sm_context_resp_pending
,
sp
))
return
;
}
// check if the session is in state Modification pending, SMF will
// ignore this message (see section 6.3.2.5 @3GPP TS 24.501)
if (sp.get()->get_pdu_session_status() ==
pdu_session_status_e::PDU_SESSION_MODIFICATION_PENDING) {
// Ignore the message
Logger::smf_app().info(
"This PDU session is in MODIFICATION_PENDING State (session ID "
"%d), ignore the message!",
decoded_nas_msg.plain.sm.header.pdu_session_identity);
return;
}
// See section 6.4.2 - UE-requested PDU Session modification procedure@
// 3GPP TS 24.501 Verify PDU Session Identity
if (sm_context_req_msg.get_pdu_session_id() !=
decoded_nas_msg.plain.sm.header.pdu_session_identity) {
// TODO: PDU Session ID mismatch
}
// PTI
Logger::smf_app().info(
"PTI %d",
decoded_nas_msg.plain.sm.header.procedure_transaction_identity);
procedure_transaction_id_t pti = {
.procedure_transaction_id =
decoded_nas_msg.plain.sm.header.procedure_transaction_identity};
n11_sm_context_resp->res.set_pti(pti);
// Message Type
// TODO: _5GSMCapability
// TODO: Cause
// TODO: maximum_number_of_supported_packet_filters
// TODO: AlwaysonPDUSessionRequested
// TODO: IntergrityProtectionMaximumDataRate
// Process QoS rules and Qos Flow descriptions
update_qos_info(sp, sm_context_resp_pending->res, decoded_nas_msg);
// TODO: MappedEPSBearerContexts
// TODO: ExtendedProtocolConfigurationOptions
// section 6.3.2. Network-requested PDU Session modification procedure @
// 3GPP TS 24.501 requested QoS rules (including packet filters) and/or
// requested QoS flow descriptions session-AMBR, session TMBR
// PTI or UE capability
// Create a N1 SM (PDU Session Modification Command) and N2 SM (PDU
// Session Resource Modify Request Transfer IE)
std::string n1_sm_msg_to_be_created, n1_sm_msg_hex_to_be_created;
std::string n2_sm_info_to_be_created, n2_sm_info_hex_to_be_created;
// N1 SM (PDU Session Modification Command)
if (not smf_n1::get_instance()
.create_n1_pdu_session_modification_command(
n11_sm_context_resp->res, n1_sm_msg_to_be_created,
cause_value_5gsm_e::CAUSE_0_UNKNOWN) or
// N2 SM (PDU Session Resource Modify Request Transfer IE)
not smf_n2::get_instance()
.create_n2_pdu_session_resource_modify_request_transfer(
n11_sm_context_resp->res,
n2_sm_info_type_e::PDU_RES_MOD_REQ,
n2_sm_info_to_be_created)) {
smf_app_inst->trigger_http_response(
http_status_code_e::HTTP_STATUS_CODE_500_INTERNAL_SERVER_ERROR,
smreq->pid, N11_SESSION_UPDATE_SM_CONTEXT_RESPONSE);
// free_wrapper((void **)&qos_flow_description);
free_wrapper((void**) &decoded_nas_msg.plain.sm
.pdu_session_modification_request.qosflowdescriptions
.qosflowdescriptionscontents);
return;
}
smf_app_inst->convert_string_2_hex(
n1_sm_msg_to_be_created, n1_sm_msg_hex_to_be_created);
smf_app_inst->convert_string_2_hex(
n2_sm_info_to_be_created, n2_sm_info_hex_to_be_created);
n11_sm_context_resp->res.set_n1_sm_message(n1_sm_msg_hex_to_be_created);
n11_sm_context_resp->res.set_n2_sm_information(
n2_sm_info_hex_to_be_created);
n11_sm_context_resp->res.set_n2_sm_info_type("PDU_RES_MOD_REQ");
// Fill the json part
nlohmann::json json_data = {};
// N1SM
json_data["n1MessageContainer"]["n1MessageClass"] = N1N2_MESSAGE_CLASS;
json_data["n1MessageContainer"]["n1MessageContent"]["contentId"] =
N1_SM_CONTENT_ID;
json_data["n2InfoContainer"]["n2InformationClass"] = N1N2_MESSAGE_CLASS;
json_data["n2InfoContainer"]["smInfo"]["n2InfoContent"]["ngapIeType"] =
"PDU_RES_MOD_REQ"; // NGAP message
json_data["n2InfoContainer"]["smInfo"]["n2InfoContent"]["ngapData"]
["contentId"] = N2_SM_CONTENT_ID;
json_data["n2InfoContainer"]["smInfo"]["PduSessionId"] =
n11_sm_context_resp->res.get_pdu_session_id();
n11_sm_context_resp->res.set_json_data(json_data);
// Update PDU Session status
sp.get()->set_pdu_session_status(
pdu_session_status_e::PDU_SESSION_MODIFICATION_PENDING);
// start timer T3591
// get smf_pdu_session and set the corresponding timer
sp.get()->timer_T3591 = itti_inst->timer_setup(
T3591_TIMER_VALUE_SEC, 0, TASK_SMF_APP, TASK_SMF_APP_TRIGGER_T3591,
sm_context_req_msg.get_pdu_session_id());
sm_context_resp_pending->session_procedure_type = procedure_type;
// don't need to create a procedure to update UPF
free_wrapper(
(void**) &decoded_nas_msg.plain.sm.pdu_session_modification_request
.qosflowdescriptions.qosflowdescriptionscontents);
*/
}
break
;
// PDU_SESSION_MODIFICATION_COMPLETE - PDU Session Modification
case
PDU_SESSION_MODIFICATION_COMPLETE
:
{
// PDU Session Modification
// procedure (UE-initiated/Network-requested) (step 3) PDU Session
// Modification Command Complete
case
PDU_SESSION_MODIFICATION_COMPLETE
:
{
// PDU Session Modification procedure (Section 4.3.3.2@3GPP TS 23.502)
Logger
::
smf_app
().
debug
(
"PDU_SESSION_MODIFICATION_COMPLETE"
);
procedure_type
=
session_management_procedures_type_e
::
PDU_SESSION_MODIFICATION_UE_INITIATED_STEP3
;
if
(
!
handle_pdu_session_modification_complete
(
decoded_nas_msg
,
smreq
,
sm_context_resp_pending
,
sp
))
return
;
/* see section 6.3.2.3@3GPP TS 24.501 V16.1.0
Upon receipt of a PDU SESSION MODIFICATION COMPLETE message, the SMF
shall stop timer T3591 and shall consider the PDU session as modified.
If the selected SSC mode of the PDU session is "SSC mode 3" and the PDU
SESSION MODIFICATION COMMAND message included 5GSM cause #39
"reactivation requested", the SMF shall start timer T3593. If the PDU
Session Address Lifetime value is sent to the UE in the PDU SESSION
MODIFICATION COMMAND message then timer T3593 shall be started with the
same value, otherwise it shall use a default value.
*/
/*
// Update PDU Session status -> ACTIVE
sp.get()->set_pdu_session_status(
pdu_session_status_e::PDU_SESSION_ACTIVE);
// stop T3591
itti_inst->timer_remove(sp.get()->timer_T3591);
sm_context_resp_pending->session_procedure_type = procedure_type;
if
(
!
handle_pdu_session_modification_complete
(
decoded_nas_msg
,
smreq
,
sm_context_resp_pending
,
sp
))
return
;
// don't need to create a procedure to update UPF
*/
}
break
;
// PDU_SESSION_MODIFICATION_COMMAND_REJECT - PDU Session Modification
// Procedure
case
PDU_SESSION_MODIFICATION_COMMAND_REJECT
:
{
// PDU_SESSION_MODIFICATION_COMMAND_REJECT
// PDU Session Modification procedure (Section 4.3.3.2@3GPP TS 23.502)
Logger
::
smf_app
().
debug
(
"PDU_SESSION_MODIFICATION_COMMAND_REJECT"
);
procedure_type
=
session_management_procedures_type_e
::
PDU_SESSION_MODIFICATION_UE_INITIATED_STEP3
;
if
(
!
handle_pdu_session_modification_command_reject
(
decoded_nas_msg
,
smreq
,
sm_context_resp_pending
,
sp
))
return
;
/*
// Verify PDU Session Identity
if (sm_context_req_msg.get_pdu_session_id() !=
decoded_nas_msg.plain.sm.header.pdu_session_identity) {
// TODO: PDU Session ID mismatch
}
Logger::smf_app().info(
"PTI %d",
decoded_nas_msg.plain.sm.header.procedure_transaction_identity);
procedure_transaction_id_t pti = {
.procedure_transaction_id =
decoded_nas_msg.plain.sm.header.procedure_transaction_identity};
n11_sm_context_resp->res.set_pti(pti);
// Message Type
//_5GSMCause
// presence
// ExtendedProtocolConfigurationOptions
if (decoded_nas_msg.plain.sm.pdu_session_modification_command_reject
._5gsmcause ==
static_cast<uint8_t>(
cause_value_5gsm_e::CAUSE_43_INVALID_PDU_SESSION_IDENTITY)) {
// Update PDU Session status -> INACTIVE
sp.get()->set_pdu_session_status(
pdu_session_status_e::PDU_SESSION_INACTIVE);
// TODO: Release locally the existing PDU Session (see
// section 6.3.2.5@3GPP TS 24.501)
} else if (
sp.get()->get_pdu_session_status() ==
pdu_session_status_e::PDU_SESSION_MODIFICATION_PENDING) {
// Update PDU Session status -> ACTIVE
sp.get()->set_pdu_session_status(
pdu_session_status_e::PDU_SESSION_ACTIVE);
}
// stop T3591
itti_inst->timer_remove(sp.get()->timer_T3591);
sm_context_resp_pending->session_procedure_type = procedure_type;
if
(
!
handle_pdu_session_modification_command_reject
(
decoded_nas_msg
,
smreq
,
sm_context_resp_pending
,
sp
))
return
;
// don't need to create a procedure to update UPF
*/
}
break
;
// PDU Session Release UE-Initiated (Step 1)
case
PDU_SESSION_RELEASE_REQUEST
:
{
// PDU Session Release procedure (Section 4.3.4@3GPP TS 23.502)
// PDU Session Release UE-Initiated (Step 1)
Logger
::
smf_app
().
debug
(
"PDU_SESSION_RELEASE_REQUEST"
);
Logger
::
smf_app
().
info
(
"PDU Session Release (UE-Initiated), processing N1 SM Information"
);
procedure_type
=
session_management_procedures_type_e
::
PDU_SESSION_RELEASE_UE_REQUESTED_STEP1
;
if
(
!
handle_pdu_session_release_request
(
decoded_nas_msg
,
smreq
,
sm_context_resp_pending
,
sp
))
return
;
/*
// verify PDU Session ID
if (sm_context_req_msg.get_pdu_session_id() !=
decoded_nas_msg.plain.sm.header.pdu_session_identity) {
// TODO: PDU Session ID mismatch
}
// Abnormal cases in network side (see section 6.4.3.6 @3GPP TS 24.501)
if (sp.get()->get_pdu_session_status() ==
pdu_session_status_e::PDU_SESSION_INACTIVE) {
Logger::smf_app().warn(
"PDU Session status: INACTIVE, send PDU Session Release Reject "
"to UE!");
if (smf_n1::get_instance().create_n1_pdu_session_release_reject(
sm_context_req_msg, n1_sm_msg,
cause_value_5gsm_e::CAUSE_43_INVALID_PDU_SESSION_IDENTITY)) {
smf_app_inst->convert_string_2_hex(n1_sm_msg, n1_sm_msg_hex);
// trigger to send reply to AMF
smf_app_inst->trigger_update_context_error_response(
http_status_code_e::HTTP_STATUS_CODE_403_FORBIDDEN,
PDU_SESSION_APPLICATION_ERROR_NETWORK_FAILURE, n1_sm_msg_hex,
smreq->pid);
} else {
smf_app_inst->trigger_http_response(
http_status_code_e::HTTP_STATUS_CODE_500_INTERNAL_SERVER_ERROR,
smreq->pid, N11_SESSION_UPDATE_SM_CONTEXT_RESPONSE);
}
return;
}
// Abnormal cases in network side (see section 6.3.3.5 @3GPP TS 24.501)
if (sp.get()->get_pdu_session_status() ==
pdu_session_status_e::PDU_SESSION_INACTIVE_PENDING) {
// Ignore the message
Logger::smf_app().info(
"A PDU Session Release Command has been sent for this session "
"(session ID %d), ignore the message!",
decoded_nas_msg.plain.sm.header.pdu_session_identity);
if
(
!
handle_pdu_session_release_request
(
decoded_nas_msg
,
smreq
,
sm_context_resp_pending
,
sp
))
return
;
}
Logger::smf_app().info(
"PTI %d",
decoded_nas_msg.plain.sm.header.procedure_transaction_identity);
procedure_transaction_id_t pti = {
.procedure_transaction_id =
decoded_nas_msg.plain.sm.header.procedure_transaction_identity};
n11_sm_context_resp->res.set_pti(pti);
// Message Type
// Presence
// 5GSM Cause
// Extended Protocol Configuration Options
// Release the resources related to this PDU Session (in Procedure)
// get the associated QoS flows: to be used for PFCP Session
// Modification procedure
std::vector<smf_qos_flow> qos_flows;
sp.get()->get_qos_flows(qos_flows);
for (auto i : qos_flows) {
smreq->req.add_qfi(i.qfi.qfi);
}
*/
// need to update UPF accordingly
update_upf
=
true
;
}
break
;
// PDU Session Release UE-Initiated (Step 3)
case
PDU_SESSION_RELEASE_COMPLETE
:
{
// PDU Session Release procedure
// PDU Session Release UE-Initiated (Step 3)
Logger
::
smf_app
().
debug
(
"PDU_SESSION_RELEASE_COMPLETE"
);
Logger
::
smf_app
().
info
(
"PDU Session Release Complete (UE-Initiated), processing N1 SM "
...
...
@@ -2614,74 +2345,10 @@ void smf_context::handle_pdu_session_update_sm_context_request(
procedure_type
=
session_management_procedures_type_e
::
PDU_SESSION_RELEASE_UE_REQUESTED_STEP3
;
if
(
!
handle_pdu_session_release_complete
(
decoded_nas_msg
,
smreq
,
sm_context_resp_pending
,
sp
))
return
;
/*
// verify PDU Session ID
if (sm_context_req_msg.get_pdu_session_id() !=
decoded_nas_msg.plain.sm.header.pdu_session_identity) {
// TODO: PDU Session ID mismatch
}
Logger::smf_app().info(
"PTI %d",
decoded_nas_msg.plain.sm.header.procedure_transaction_identity);
procedure_transaction_id_t pti = {
.procedure_transaction_id =
decoded_nas_msg.plain.sm.header.procedure_transaction_identity};
if (decoded_nas_msg.plain.sm.header.message_type !=
PDU_SESSION_RELEASE_COMPLETE) {
// TODO: Message Type mismatch
}
// 5GSM Cause
// Extended Protocol Configuration Options
// Update PDU Session status -> INACTIVE
sp.get()->set_pdu_session_status(
pdu_session_status_e::PDU_SESSION_INACTIVE);
// Stop timer T3592
itti_inst->timer_remove(sp.get()->timer_T3592);
sm_context_resp_pending->session_procedure_type = procedure_type;
if
(
!
handle_pdu_session_release_complete
(
decoded_nas_msg
,
smreq
,
sm_context_resp_pending
,
sp
))
return
;
// don't need to create a procedure to update UPF
// TODO: SMF invokes Nsmf_PDUSession_SMContextStatusNotify to notify AMF
// that the SM context for this PDU Session is released
scid_t scid = {};
try {
scid = std::stoi(smreq->scid);
} catch (const std::exception& err) {
Logger::smf_app().warn(
"Received a PDU Session Update SM Context Request, couldn't "
"retrieve the corresponding SMF context, ignore message!");
// TODO: return;
}
event_sub.sm_context_status(
scid,
static_cast<uint32_t>(
sm_context_status_e::SM_CONTEXT_STATUS_RELEASED),
smreq->http_version);
// Get SUPI
supi64_t supi64 = smf_supi_to_u64(sm_context_req_msg.get_supi());
// Trigger PDU Session Release event notification
event_sub.ee_pdu_session_release(
supi64, sm_context_req_msg.get_pdu_session_id(),
smreq->http_version);
// TODO: if dynamic PCC applied, SMF invokes an SM Policy Association
// Termination
// TODO: SMF unsubscribes from Session Management Subscription data
// changes notification from UDM by invoking Numd_SDM_Unsubscribe
if (sd.get()->get_number_pdu_sessions() == 0) {
Logger::smf_app().debug(
"Unsubscribe from Session Management Subscription data changes "
"notification from UDM");
// TODO: unsubscribes from Session Management Subscription data
// changes notification from UDM
}
// TODO: Invoke Nudm_UECM_Deregistration
*/
}
break
;
// To be verified
...
...
@@ -2716,7 +2383,9 @@ void smf_context::handle_pdu_session_update_sm_context_request(
Logger
::
smf_app
().
info
(
"PDU Session Resource Setup Response Transfer"
);
if
(
!
handle_pdu_session_resource_setup_response_transfer
(
n2_sm_information
,
smreq
))
return
;
if
(
!
handle_pdu_session_resource_setup_response_transfer
(
n2_sm_information
,
smreq
))
return
;
if
(
sm_context_req_msg
.
rat_type_is_set
()
and
sm_context_req_msg
.
an_type_is_set
())
{
...
...
@@ -2731,249 +2400,65 @@ void smf_context::handle_pdu_session_update_sm_context_request(
"PDU Session Establishment Request, processing N2 SM "
"Information"
);
}
/*
// Ngap_PDUSessionResourceSetupResponseTransfer
std::shared_ptr<Ngap_PDUSessionResourceSetupResponseTransfer_t>
decoded_msg = std::make_shared<
Ngap_PDUSessionResourceSetupResponseTransfer_t>();
int decode_status = smf_n2::get_instance().decode_n2_sm_information(
decoded_msg, n2_sm_information);
if (decode_status == RETURNerror) {
// error, send error to AMF
Logger::smf_app().warn(
"Decode N2 SM (Ngap_PDUSessionResourceSetupResponseTransfer) "
"failed!");
// PDU Session Establishment Reject
// 24.501: response with a 5GSM STATUS message including cause "#95
// Semantically incorrect message"
if (smf_n1::get_instance().create_n1_pdu_session_establishment_reject(
sm_context_req_msg, n1_sm_msg,
cause_value_5gsm_e::
CAUSE_95_SEMANTICALLY_INCORRECT_MESSAGE)) {
smf_app_inst->convert_string_2_hex(
n1_sm_msg, n1_sm_msg_hex); // TODO: need N1SM?
// trigger to send reply to AMF
smf_app_inst->trigger_update_context_error_response(
http_status_code_e::HTTP_STATUS_CODE_403_FORBIDDEN,
PDU_SESSION_APPLICATION_ERROR_N2_SM_ERROR, smreq->pid);
} else {
smf_app_inst->trigger_http_response(
http_status_code_e::HTTP_STATUS_CODE_500_INTERNAL_SERVER_ERROR,
smreq->pid, N11_SESSION_UPDATE_SM_CONTEXT_RESPONSE);
}
return;
}
// store AN Tunnel Info + list of accepted QFIs
pfcp::fteid_t dl_teid = {};
memcpy(
&dl_teid.teid,
decoded_msg->dLQosFlowPerTNLInformation.uPTransportLayerInformation
.choice.gTPTunnel->gTP_TEID.buf,
TEID_GRE_KEY_LENGTH);
memcpy(
&dl_teid.ipv4_address,
decoded_msg->dLQosFlowPerTNLInformation.uPTransportLayerInformation
.choice.gTPTunnel->transportLayerAddress.buf,
4);
dl_teid.teid = ntohl(dl_teid.teid);
dl_teid.v4 = 1; // Only V4 for now
smreq->req.set_dl_fteid(dl_teid);
Logger::smf_app().debug(
"DL GTP F-TEID (AN F-TEID) "
"0x%" PRIx32 " ",
dl_teid.teid);
Logger::smf_app().debug(
"uPTransportLayerInformation (AN IP Addr) %s",
conv::toString(dl_teid.ipv4_address).c_str());
for (int i = 0; i < decoded_msg->dLQosFlowPerTNLInformation
.associatedQosFlowList.list.count;
i++) {
pfcp::qfi_t qfi((uint8_t)(decoded_msg->dLQosFlowPerTNLInformation
.associatedQosFlowList.list.array[i])
->qosFlowIdentifier);
smreq->req.add_qfi(qfi);
Logger::smf_app().debug(
"QoSFlowPerTNLInformation, AssociatedQosFlowList, QFI %d",
(decoded_msg->dLQosFlowPerTNLInformation.associatedQosFlowList
.list.array[i])
->qosFlowIdentifier);
}
*/
// need to update UPF accordingly
update_upf
=
true
;
}
break
;
case
n2_sm_info_type_e
:
:
PDU_RES_SETUP_FAIL
:
{
// PDU Session Establishment procedure
// PDU Session Resource Setup Unsuccessful Transfer
case
n2_sm_info_type_e
:
:
PDU_RES_SETUP_FAIL
:
{
Logger
::
smf_app
().
info
(
"PDU Session Resource Setup Unsuccessful Transfer"
);
if
(
!
handle_pdu_session_resource_setup_unsuccessful_transfer
(
n2_sm_information
,
smreq
))
return
;
/*
// Ngap_PDUSessionResourceSetupUnsuccessfulTransfer
std::shared_ptr<Ngap_PDUSessionResourceSetupUnsuccessfulTransfer_t>
decoded_msg = std::make_shared<
Ngap_PDUSessionResourceSetupUnsuccessfulTransfer_t>();
int decode_status = smf_n2::get_instance().decode_n2_sm_information(
decoded_msg, n2_sm_information);
if (decode_status == RETURNerror) {
Logger::smf_app().warn(
"Decode N2 SM (Ngap_PDUSessionResourceSetupUnsuccessfulTransfer) "
"failed!");
// trigger to send reply to AMF
smf_app_inst->trigger_update_context_error_response(
http_status_code_e::HTTP_STATUS_CODE_403_FORBIDDEN,
PDU_SESSION_APPLICATION_ERROR_N2_SM_ERROR, smreq->pid);
if
(
!
handle_pdu_session_resource_setup_unsuccessful_transfer
(
n2_sm_information
,
smreq
))
return
;
}
// Logger::smf_app().info("PDU Session Resource Setup Unsuccessful
// Transfer cause %d",decoded_msg->cause ); PDU Session Establishment
// Reject, 24.501 cause "#26 Insufficient resources"
if (smf_n1::get_instance().create_n1_pdu_session_establishment_reject(
smreq->req, n1_sm_msg,
cause_value_5gsm_e::CAUSE_26_INSUFFICIENT_RESOURCES)) {
smf_app_inst->convert_string_2_hex(n1_sm_msg, n1_sm_msg_hex);
// trigger to send reply to AMF
smf_app_inst->trigger_update_context_error_response(
http_status_code_e::HTTP_STATUS_CODE_403_FORBIDDEN,
PDU_SESSION_APPLICATION_ERROR_UE_NOT_RESPONDING, n1_sm_msg_hex,
smreq->pid);
// TODO: Need release established resources?
} else {
smf_app_inst->trigger_http_response(
http_status_code_e::HTTP_STATUS_CODE_500_INTERNAL_SERVER_ERROR,
smreq->pid, N11_SESSION_UPDATE_SM_CONTEXT_RESPONSE);
}
return;
*/
// don't need to update UPF
}
break
;
case
n2_sm_info_type_e
:
:
PDU_RES_MOD_RSP
:
{
// PDU Session Modification procedure (UE-initiated,
// Section 4.3.3.2@3GPP TS 23.502 or SMF-Requested)(Step 2)
case
n2_sm_info_type_e
:
:
PDU_RES_MOD_RSP
:
{
Logger
::
smf_app
().
info
(
"PDU Session Modification Procedure, processing N2 SM Information"
);
procedure_type
=
session_management_procedures_type_e
::
PDU_SESSION_MODIFICATION_UE_INITIATED_STEP2
;
if
(
!
handle_pdu_session_resource_modify_response_transfer
(
n2_sm_information
,
smreq
))
return
;
/*
// Ngap_PDUSessionResourceModifyResponseTransfer
std::shared_ptr<Ngap_PDUSessionResourceModifyResponseTransfer_t>
decoded_msg = std::make_shared<
Ngap_PDUSessionResourceModifyResponseTransfer_t>();
int decode_status = smf_n2::get_instance().decode_n2_sm_information(
decoded_msg, n2_sm_information);
if (decode_status == RETURNerror) {
Logger::smf_app().warn(
"Decode N2 SM (Ngap_PDUSessionResourceModifyResponseTransfer) "
"failed!");
// trigger to send reply to AMF
smf_app_inst->trigger_update_context_error_response(
http_status_code_e::HTTP_STATUS_CODE_403_FORBIDDEN,
PDU_SESSION_APPLICATION_ERROR_N2_SM_ERROR, smreq->pid);
if
(
!
handle_pdu_session_resource_modify_response_transfer
(
n2_sm_information
,
smreq
))
return
;
}
// see section 8.2.3 (PDU Session Resource Modify) @3GPP TS 38.413
// if dL_NGU_UP_TNLInformation is included, it shall be considered as
// the new DL transport layer addr for the PDU session (should be
// verified)
// TODO: may include uL_NGU_UP_TNLInformation (mapping between each new
// DL transport layer address and the corresponding UL transport layer
// address)
pfcp::fteid_t dl_teid;
memcpy(
&dl_teid.teid,
decoded_msg->dL_NGU_UP_TNLInformation->choice.gTPTunnel->gTP_TEID
.buf,
TEID_GRE_KEY_LENGTH);
memcpy(
&dl_teid.ipv4_address,
decoded_msg->dL_NGU_UP_TNLInformation->choice.gTPTunnel
->transportLayerAddress.buf,
4);
dl_teid.teid = ntohl(dl_teid.teid);
dl_teid.v4 = 1; // Only v4 for now
smreq->req.set_dl_fteid(dl_teid);
// list of Qos Flows which have been successfully setup or modified
if (decoded_msg->qosFlowAddOrModifyResponseList) {
for (int i = 0;
i < decoded_msg->qosFlowAddOrModifyResponseList->list.count;
i++) {
smreq->req.add_qfi(
(decoded_msg->qosFlowAddOrModifyResponseList->list.array[i])
->qosFlowIdentifier);
}
}
// TODO: list of QoS Flows which have failed to be modified,
// qosFlowFailedToAddOrModifyList
// TODO: additionalDLQosFlowPerTNLInformation
*/
// need to update UPF accordingly
update_upf
=
true
;
}
break
;
// PDU Session Modification procedure
case
n2_sm_info_type_e
:
:
PDU_RES_MOD_FAIL
:
{
// PDU Session Modification procedure
Logger
::
smf_app
().
info
(
"PDU_RES_MOD_FAIL"
);
// TODO: To be completed
}
break
;
case
n2_sm_info_type_e
:
:
PDU_RES_REL_RSP
:
{
// PDU Session Release procedure (UE-initiated, Section 4.3.4.2@3GPP
// TS 23.502 or SMF-Requested)(Step 2)
case
n2_sm_info_type_e
:
:
PDU_RES_REL_RSP
:
{
Logger
::
smf_app
().
info
(
"PDU Session Release (UE-initiated), processing N2 SM Information"
);
procedure_type
=
session_management_procedures_type_e
::
PDU_SESSION_RELEASE_UE_REQUESTED_STEP2
;
if
(
!
handle_pdu_session_resource_release_response_transfer
(
n2_sm_information
,
smreq
))
return
;
sm_context_resp_pending
->
session_procedure_type
=
session_management_procedures_type_e
::
PDU_SESSION_RELEASE_UE_REQUESTED_STEP2
;
/*
// TODO: SMF does nothing (Step 7, section 4.3.4.2@3GPP TS 23.502)
// Ngap_PDUSessionResourceReleaseResponseTransfer
std::shared_ptr<Ngap_PDUSessionResourceReleaseResponseTransfer_t>
decoded_msg = std::make_shared<
Ngap_PDUSessionResourceReleaseResponseTransfer_t>();
int decode_status = smf_n2::get_instance().decode_n2_sm_information(
decoded_msg, n2_sm_information);
if (decode_status == RETURNerror) {
Logger::smf_app().warn(
"Decode N2 SM (Ngap_PDUSessionResourceReleaseResponseTransfer) "
"failed!");
// trigger to send reply to AMF
smf_app_inst->trigger_update_context_error_response(
http_status_code_e::HTTP_STATUS_CODE_403_FORBIDDEN,
PDU_SESSION_APPLICATION_ERROR_N2_SM_ERROR, smreq->pid);
if
(
!
handle_pdu_session_resource_release_response_transfer
(
n2_sm_information
,
smreq
))
return
;
}
sm_context_resp_pending->session_procedure_type = procedure_type;
sm_context_resp_pending
->
session_procedure_type
=
session_management_procedures_type_e
::
PDU_SESSION_RELEASE_UE_REQUESTED_STEP2
;
// don't need to create a procedure to update UPF
smf_app_inst->trigger_http_response(
http_status_code_e::HTTP_STATUS_CODE_200_OK, smreq->pid,
N11_SESSION_UPDATE_SM_CONTEXT_RESPONSE);
*/
}
break
;
default:
{
...
...
@@ -2991,65 +2476,11 @@ void smf_context::handle_pdu_session_update_sm_context_request(
procedure_type
=
session_management_procedures_type_e
::
SERVICE_REQUEST_UE_TRIGGERED_STEP1
;
handle_service_request
(
n2_sm_info
,
smreq
,
sm_context_resp_pending
,
sp
);
/*
// Update upCnxState
sp.get()->set_upCnx_state(upCnx_state_e::UPCNX_STATE_ACTIVATING);
// get QFIs associated with PDU session ID
std::vector<smf_qos_flow> qos_flows = {};
sp.get()->get_qos_flows(qos_flows);
for (auto i : qos_flows) {
smreq->req.add_qfi(i.qfi.qfi);
qos_flow_context_updated qcu = {};
qcu.set_cause(REQUEST_ACCEPTED);
qcu.set_qfi(i.qfi);
qcu.set_ul_fteid(i.ul_fteid);
qcu.set_qos_profile(i.qos_profile);
sm_context_resp_pending->res.add_qos_flow_context_updated(qcu);
}
sm_context_resp_pending->session_procedure_type = procedure_type;
// Create N2 SM Information: PDU Session Resource Setup Request Transfer IE
// N2 SM Information
smf_n2::get_instance()
.create_n2_pdu_session_resource_setup_request_transfer(
sm_context_resp_pending->res, n2_sm_info_type_e::PDU_RES_SETUP_REQ,
n2_sm_info);
smf_app_inst->convert_string_2_hex(n2_sm_info, n2_sm_info_hex);
sm_context_resp_pending->res.set_n2_sm_information(n2_sm_info_hex);
// fill the content of SmContextUpdatedData
nlohmann::json json_data = {};
json_data["n2InfoContainer"]["n2InformationClass"] = N1N2_MESSAGE_CLASS;
json_data["n2InfoContainer"]["smInfo"]["PduSessionId"] =
sm_context_resp_pending->res.get_pdu_session_id();
json_data["n2InfoContainer"]["smInfo"]["n2InfoContent"]["ngapData"]
["contentId"] = N2_SM_CONTENT_ID;
json_data["n2InfoContainer"]["smInfo"]["n2InfoContent"]["ngapIeType"] =
"PDU_RES_SETUP_REQ"; // NGAP message
json_data["upCnxState"] = "ACTIVATING";
sm_context_resp_pending->res.set_json_data(json_data);
if
(
!
handle_service_request
(
n2_sm_info
,
smreq
,
sm_context_resp_pending
,
sp
))
return
;
// Update upCnxState to ACTIVATING
sp.get()->set_upCnx_state(upCnx_state_e::UPCNX_STATE_ACTIVATING);
*/
// do not need update UPF
update_upf
=
false
;
/* // TODO: If new UPF is used, need to send N4 Session Modification
// Request/Response to new/old UPF
// Accept the activation of UP connection and continue to using the current
// UPF
// TODO: Accept the activation of UP connection and select a new UPF
// Reject the activation of UP connection
// SMF fails to find a suitable I-UPF: i) trigger re-establishment of PDU
// Session; or ii) keep PDU session but reject the activation of UP
// connection; or iii) release PDU session
*/
}
// Step 4. For AMF-initiated Session Release (with release indication)
...
...
@@ -3066,7 +2497,7 @@ void smf_context::handle_pdu_session_update_sm_context_request(
update_upf
=
true
;
}
// Step 5. Create a procedure for update
sm
context and let the procedure
// Step 5. Create a procedure for update
SM
context and let the procedure
// handle the request if necessary
if
(
update_upf
)
{
session_update_sm_context_procedure
*
proc
=
...
...
src/smf_app/smf_context.hpp
View file @
a9935948
...
...
@@ -648,6 +648,146 @@ class smf_context : public std::enable_shared_from_this<smf_context> {
void
handle_pdu_session_modification_network_requested
(
std
::
shared_ptr
<
itti_nx_trigger_pdu_session_modification
>
msg
);
/*
* Handle PDU Session Modification Request
* @param [nas_message_t&] nas_msg: NAS message received from AMF
* @param [std::shared_ptr<itti_n11_update_sm_context_request>&]
* sm_context_request: Request message
* @param [std::shared_ptr<itti_n11_update_sm_context_response>&]
* sm_context_resp: Response message
* @param [std::shared_ptr<smf_pdu_session>&] sp: PDU session
* @return True if handle successful, otherwise return false
*/
bool
handle_pdu_session_modification_request
(
nas_message_t
&
nas_msg
,
std
::
shared_ptr
<
itti_n11_update_sm_context_request
>&
sm_context_request
,
std
::
shared_ptr
<
itti_n11_update_sm_context_response
>&
sm_context_resp
,
std
::
shared_ptr
<
smf_pdu_session
>&
sp
);
/*
* Handle PDU Session Modification Complete
* @param [nas_message_t&] nas_msg: NAS message received from AMF
* @param [std::shared_ptr<itti_n11_update_sm_context_request>&]
* sm_context_request: Request message
* @param [std::shared_ptr<itti_n11_update_sm_context_response>&]
* sm_context_resp: Response message
* @param [std::shared_ptr<smf_pdu_session>&] sp: PDU session
* @return True if handle successful, otherwise return false
*/
bool
handle_pdu_session_modification_complete
(
nas_message_t
&
nas_msg
,
std
::
shared_ptr
<
itti_n11_update_sm_context_request
>&
sm_context_request
,
std
::
shared_ptr
<
itti_n11_update_sm_context_response
>&
sm_context_resp
,
std
::
shared_ptr
<
smf_pdu_session
>&
sp
);
/*
* Handle PDU Session Modification Command Reject
* @param [nas_message_t&] nas_msg: NAS message received from AMF
* @param [std::shared_ptr<itti_n11_update_sm_context_request>&]
* sm_context_request: Request message
* @param [std::shared_ptr<itti_n11_update_sm_context_response>&]
* sm_context_resp: Response message
* @param [std::shared_ptr<smf_pdu_session>&] sp: PDU session
* @return True if handle successful, otherwise return false
*/
bool
handle_pdu_session_modification_command_reject
(
nas_message_t
&
nas_msg
,
std
::
shared_ptr
<
itti_n11_update_sm_context_request
>&
sm_context_request
,
std
::
shared_ptr
<
itti_n11_update_sm_context_response
>&
sm_context_resp
,
std
::
shared_ptr
<
smf_pdu_session
>&
sp
);
/*
* Handle PDU Session Release Request
* @param [nas_message_t&] nas_msg: NAS message received from AMF
* @param [std::shared_ptr<itti_n11_update_sm_context_request>&]
* sm_context_request: Request message
* @param [std::shared_ptr<itti_n11_update_sm_context_response>&]
* sm_context_resp: Response message
* @param [std::shared_ptr<smf_pdu_session>&] sp: PDU session
* @return True if handle successful, otherwise return false
*/
bool
handle_pdu_session_release_request
(
nas_message_t
&
nas_msg
,
std
::
shared_ptr
<
itti_n11_update_sm_context_request
>&
sm_context_request
,
std
::
shared_ptr
<
itti_n11_update_sm_context_response
>&
sm_context_resp
,
std
::
shared_ptr
<
smf_pdu_session
>&
sp
);
/*
* Handle PDU Session Release Complete
* @param [nas_message_t&] nas_msg: NAS message received from AMF
* @param [std::shared_ptr<itti_n11_update_sm_context_request>&]
* sm_context_request: Request message
* @param [std::shared_ptr<itti_n11_update_sm_context_response>&]
* sm_context_resp: Response message
* @param [std::shared_ptr<smf_pdu_session>&] sp: PDU session
* @return True if handle successful, otherwise return false
*/
bool
handle_pdu_session_release_complete
(
nas_message_t
&
nas_msg
,
std
::
shared_ptr
<
itti_n11_update_sm_context_request
>&
sm_context_request
,
std
::
shared_ptr
<
itti_n11_update_sm_context_response
>&
sm_context_resp
,
std
::
shared_ptr
<
smf_pdu_session
>&
sp
);
/*
* Handle Service Request
* @param [std::string&] n2_sm_information: NGAP message in form of string
* @param [std::shared_ptr<itti_n11_update_sm_context_request>&]
* sm_context_request: Request message
* @param [std::shared_ptr<itti_n11_update_sm_context_response>&]
* sm_context_resp: Response message
* @param [std::shared_ptr<smf_pdu_session>&] sp: PDU session
* @return True if handle successful, otherwise return false
*/
bool
handle_service_request
(
std
::
string
&
n2_sm_information
,
std
::
shared_ptr
<
itti_n11_update_sm_context_request
>&
sm_context_request
,
std
::
shared_ptr
<
itti_n11_update_sm_context_response
>&
sm_context_resp
,
std
::
shared_ptr
<
smf_pdu_session
>&
sp
);
/*
* Handle PDU Session Resource Setup Response Transfer
* @param [std::string&] n2_sm_information: NGAP message in form of string
* @param [std::shared_ptr<itti_n11_update_sm_context_request>&]
* sm_context_request: Request message
* @return True if handle successful, otherwise return false
*/
bool
handle_pdu_session_resource_setup_response_transfer
(
std
::
string
&
n2_sm_information
,
std
::
shared_ptr
<
itti_n11_update_sm_context_request
>&
sm_context_request
);
/*
* Handle PDU Session Resource Setup Unsuccessful Transfer
* @param [std::string&] n2_sm_information: NGAP message in form of string
* @param [std::shared_ptr<itti_n11_update_sm_context_request>&]
* sm_context_request: Request message
* @return True if handle successful, otherwise return false
*/
bool
handle_pdu_session_resource_setup_unsuccessful_transfer
(
std
::
string
&
n2_sm_information
,
std
::
shared_ptr
<
itti_n11_update_sm_context_request
>&
sm_context_request
);
/*
* Handle PDU Session Resource Modify Response Transfer
* @param [std::string&] n2_sm_information: NGAP message in form of string
* @param [std::shared_ptr<itti_n11_update_sm_context_request>&]
* sm_context_request: Request message
* @return True if handle successful, otherwise return false
*/
bool
handle_pdu_session_resource_modify_response_transfer
(
std
::
string
&
n2_sm_information
,
std
::
shared_ptr
<
itti_n11_update_sm_context_request
>&
sm_context_request
);
/*
* Handle PDU Session Resource Release Response Transfer
* @param [std::string&] n2_sm_information: NGAP message in form of string
* @param [std::shared_ptr<itti_n11_update_sm_context_request>&]
* sm_context_request: Request message
* @return True if handle successful, otherwise return false
*/
bool
handle_pdu_session_resource_release_response_transfer
(
std
::
string
&
n2_sm_information
,
std
::
shared_ptr
<
itti_n11_update_sm_context_request
>&
sm_context_request
);
/*
* Find DNN context with name
* @param [const std::string&] dnn
...
...
@@ -849,61 +989,20 @@ class smf_context : public std::enable_shared_from_this<smf_context> {
void
handle_ee_pdu_session_release
(
supi64_t
supi
,
pdu_session_id_t
pdu_session_id
,
uint8_t
http_version
);
/*
* Update QoS information in the Response message according to the content of
* decoded NAS msg
* @param [std::shared_ptr<smf_pdu_session>&] sp: PDU session
* @param [std::shared_ptr<pdu_session_update_sm_context_response>&] res:
* Response message
* @param [const nas_message_t] nas_msg: NAS message
* @return void
*/
void
update_qos_info
(
std
::
shared_ptr
<
smf_pdu_session
>&
sp
,
smf
::
pdu_session_update_sm_context_response
&
res
,
const
nas_message_t
&
nas_msg
);
bool
handle_pdu_session_modification_request
(
nas_message_t
&
nas_msg
,
std
::
shared_ptr
<
itti_n11_update_sm_context_request
>&
sm_context_request
,
std
::
shared_ptr
<
itti_n11_update_sm_context_response
>&
sm_context_resp
,
std
::
shared_ptr
<
smf_pdu_session
>&
sp
);
bool
handle_pdu_session_modification_complete
(
nas_message_t
&
nas_msg
,
std
::
shared_ptr
<
itti_n11_update_sm_context_request
>&
sm_context_request
,
std
::
shared_ptr
<
itti_n11_update_sm_context_response
>&
sm_context_resp
,
std
::
shared_ptr
<
smf_pdu_session
>&
sp
);
bool
handle_pdu_session_modification_command_reject
(
nas_message_t
&
nas_msg
,
std
::
shared_ptr
<
itti_n11_update_sm_context_request
>&
sm_context_request
,
std
::
shared_ptr
<
itti_n11_update_sm_context_response
>&
sm_context_resp
,
std
::
shared_ptr
<
smf_pdu_session
>&
sp
);
bool
handle_pdu_session_release_request
(
nas_message_t
&
nas_msg
,
std
::
shared_ptr
<
itti_n11_update_sm_context_request
>&
sm_context_request
,
std
::
shared_ptr
<
itti_n11_update_sm_context_response
>&
sm_context_resp
,
std
::
shared_ptr
<
smf_pdu_session
>&
sp
);
bool
handle_pdu_session_release_complete
(
nas_message_t
&
nas_msg
,
std
::
shared_ptr
<
itti_n11_update_sm_context_request
>&
sm_context_request
,
std
::
shared_ptr
<
itti_n11_update_sm_context_response
>&
sm_context_resp
,
std
::
shared_ptr
<
smf_pdu_session
>&
sp
);
bool
handle_pdu_session_resource_setup_response_transfer
(
std
::
string
&
n2_sm_information
,
std
::
shared_ptr
<
itti_n11_update_sm_context_request
>&
sm_context_request
);
bool
handle_pdu_session_resource_setup_unsuccessful_transfer
(
std
::
string
&
n2_sm_information
,
std
::
shared_ptr
<
itti_n11_update_sm_context_request
>&
sm_context_request
);
bool
handle_pdu_session_resource_modify_response_transfer
(
std
::
string
&
n2_sm_information
,
std
::
shared_ptr
<
itti_n11_update_sm_context_request
>&
sm_context_request
);
bool
handle_pdu_session_resource_release_response_transfer
(
std
::
string
&
n2_sm_information
,
std
::
shared_ptr
<
itti_n11_update_sm_context_request
>&
sm_context_request
);
bool
handle_service_request
(
std
::
string
&
n2_sm_information
,
std
::
shared_ptr
<
itti_n11_update_sm_context_request
>&
sm_context_request
,
std
::
shared_ptr
<
itti_n11_update_sm_context_response
>&
sm_context_resp
,
std
::
shared_ptr
<
smf_pdu_session
>&
sp
);
private:
std
::
vector
<
std
::
shared_ptr
<
dnn_context
>>
dnns
;
std
::
vector
<
std
::
shared_ptr
<
smf_procedure
>>
pending_procedures
;
...
...
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