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
251022eb
Commit
251022eb
authored
May 05, 2020
by
Tien-Thinh Nguyen
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
finalize PDU Session Modification procedure (step 2 and 3)
parent
0d1c5fd6
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
393 additions
and
154 deletions
+393
-154
src/smf_app/smf_context.cpp
src/smf_app/smf_context.cpp
+79
-146
src/smf_app/smf_n1_n2.cpp
src/smf_app/smf_n1_n2.cpp
+105
-3
src/test/amf_client/amf-client.cpp
src/test/amf_client/amf-client.cpp
+209
-5
No files found.
src/smf_app/smf_context.cpp
View file @
251022eb
...
...
@@ -1586,17 +1586,8 @@ void smf_context::handle_pdu_session_update_sm_context_request(
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
//Send ITTI to N11 to send PDUSession_UpdateSMContext Response to AMF
Logger
::
smf_app
().
info
(
"Sending ITTI message %s to task TASK_SMF_N11"
,
sm_context_resp_pending
->
get_msg_name
());
int
ret
=
itti_inst
->
send_msg
(
sm_context_resp_pending
);
if
(
RETURNok
!=
ret
)
{
Logger
::
smf_app
().
error
(
"Could not send ITTI message %s to task TASK_SMF_N11"
,
sm_context_resp_pending
->
get_msg_name
());
}
free_wrapper
((
void
**
)
&
qos_rules_ie
);
free_wrapper
((
void
**
)
&
qos_flow_description
);
...
...
@@ -1607,20 +1598,11 @@ void smf_context::handle_pdu_session_update_sm_context_request(
//PDU Session Modification Command Complete
case
PDU_SESSION_MODIFICATION_COMPLETE
:
{
//PDU Session Modification procedure (Section 4.3.3.2@3GPP TS 23.502)
//TODO: should be verified since mentioned PDU_SESSION_MODIFICATION_COMMAND ACK in spec (see Step 11, 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
;
/* ExtendedProtocolDiscriminator extendedprotocoldiscriminator;
PDUSessionIdentity pdusessionidentity;
ProcedureTransactionIdentity proceduretransactionidentity;
MessageType messagetype;
uint8_t presence;
ExtendedProtocolConfigurationOptions extendedprotocolconfigurationoptions;
*/
/* 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
...
...
@@ -1635,18 +1617,8 @@ void smf_context::handle_pdu_session_update_sm_context_request(
//stop T3591
itti_inst
->
timer_remove
(
sp
.
get
()
->
timer_T3591
);
//don't need to create a procedure to update UPF
//Send ITTI to N11 to send PDUSession_UpdateSMContext Response to AMF
//No need to create N1/N2 Container
sm_context_resp_pending
->
session_procedure_type
=
procedure_type
;
Logger
::
smf_app
().
info
(
"Sending ITTI message %s to task TASK_SMF_N11"
,
sm_context_resp_pending
->
get_msg_name
());
int
ret
=
itti_inst
->
send_msg
(
sm_context_resp_pending
);
if
(
RETURNok
!=
ret
)
{
Logger
::
smf_app
().
error
(
"Could not send ITTI message %s to task TASK_SMF_N11"
,
sm_context_resp_pending
->
get_msg_name
());
}
//don't need to create a procedure to update UPF
}
break
;
...
...
@@ -1684,7 +1656,8 @@ void smf_context::handle_pdu_session_update_sm_context_request(
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
){
}
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
);
...
...
@@ -1693,19 +1666,8 @@ void smf_context::handle_pdu_session_update_sm_context_request(
//stop T3591
itti_inst
->
timer_remove
(
sp
.
get
()
->
timer_T3591
);
//don't need to create a procedure to update UPF
//Send ITTI to N11 to send PDUSession_UpdateSMContext Response to AMF
//No need to create N1/N2 Container
sm_context_resp_pending
->
session_procedure_type
=
procedure_type
;
Logger
::
smf_app
().
info
(
"Sending ITTI message %s to task TASK_SMF_N11"
,
sm_context_resp_pending
->
get_msg_name
());
int
ret
=
itti_inst
->
send_msg
(
sm_context_resp_pending
);
if
(
RETURNok
!=
ret
)
{
Logger
::
smf_app
().
error
(
"Could not send ITTI message %s to task TASK_SMF_N11"
,
sm_context_resp_pending
->
get_msg_name
());
}
//don't need to create a procedure to update UPF
}
break
;
...
...
@@ -1858,23 +1820,12 @@ void smf_context::handle_pdu_session_update_sm_context_request(
//Stop timer T3592
itti_inst
->
timer_remove
(
sp
.
get
()
->
timer_T3592
);
//don't need to create a procedure to update UPF
//Send ITTI to N11 to send PDUSession_UpdateSMContext Response to AMF
//No need to create N1/N2 Container
sm_context_resp_pending
->
session_procedure_type
=
procedure_type
;
Logger
::
smf_app
().
info
(
"Sending ITTI message %s to task TASK_SMF_N11"
,
sm_context_resp_pending
->
get_msg_name
());
int
ret
=
itti_inst
->
send_msg
(
sm_context_resp_pending
);
if
(
RETURNok
!=
ret
)
{
Logger
::
smf_app
().
error
(
"Could not send ITTI message %s to task TASK_SMF_N11"
,
sm_context_resp_pending
->
get_msg_name
());
}
//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
//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"
);
...
...
@@ -2007,6 +1958,7 @@ void smf_context::handle_pdu_session_update_sm_context_request(
(
decoded_msg
->
dLQosFlowPerTNLInformation
.
associatedQosFlowList
.
list
.
array
[
i
])
->
qosFlowIdentifier
);
}
//need to update UPF accordingly
update_upf
=
true
;
}
...
...
@@ -2016,7 +1968,7 @@ void smf_context::handle_pdu_session_update_sm_context_request(
case
n2_sm_info_type_e
:
:
PDU_RES_MOD_RSP
:
{
Logger
::
smf_app
().
info
(
"PDU_RES_MOD_RSP"
);
Logger
::
smf_app
().
info
(
"PDU Session Modification, processing N2 SM Information"
);
"PDU Session Modification
Procedure
, processing N2 SM Information"
);
procedure_type
=
session_management_procedures_type_e
::
PDU_SESSION_MODIFICATION_UE_INITIATED_STEP2
;
...
...
@@ -2026,63 +1978,54 @@ void smf_context::handle_pdu_session_update_sm_context_request(
std
::
make_shared
<
Ngap_PDUSessionResourceModifyResponseTransfer_t
>
();
int
decode_status
=
smf_n1_n2_inst
.
decode_n2_sm_information
(
decoded_msg
,
n2_sm_information
);
if
(
decode_status
==
RETURNerror
)
{
Logger
::
smf_api_server
().
warn
(
"asn_decode failed"
);
//send error to AMF
Logger
::
smf_app
().
warn
(
"Decode N2 SM (Ngap_PDUSessionResourceModifyResponseTransfer) failed!"
);
problem_details
.
setCause
(
pdu_session_application_error_e2str
[
PDU_SESSION_APPLICATION_ERROR_N2_SM_ERROR
]);
smContextUpdateError
.
setError
(
problem_details
);
//TODO: need to verify with/without N1 SM
refToBinaryData
.
setContentId
(
N1_SM_CONTENT_ID
);
smContextUpdateError
.
setN1SmMsg
(
refToBinaryData
);
//PDU Session Establishment Reject
//24.501: response with a 5GSM STATUS message including cause "#95 Semantically incorrect message"
smf_n1_n2_inst
.
create_n1_sm_container
(
sm_context_req_msg
,
PDU_SESSION_ESTABLISHMENT_REJECT
,
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
);
smf_n11_inst
->
send_pdu_session_update_sm_context_response
(
smreq
->
http_response
,
smContextUpdateError
,
Pistache
::
Http
::
Code
::
Forbidden
,
n1_sm_msg_hex
);
Pistache
::
Http
::
Code
::
Forbidden
);
return
;
}
/*
struct Ngap_UPTransportLayerInformation *dL_NGU_UP_TNLInformation;
struct Ngap_UPTransportLayerInformation *uL_NGU_UP_TNLInformation;
struct Ngap_QosFlowAddOrModifyResponseList *qosFlowAddOrModifyResponseList;
struct Ngap_QosFlowPerTNLInformationList *additionalDLQosFlowPerTNLInformation;
struct Ngap_QosFlowListWithCause *qosFlowFailedToAddOrModifyList;
struct Ngap_ProtocolExtensionContainer *iE_Extensions;
*/
//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)
fteid_t
dl_teid
;
memcpy
(
&
dl_teid
.
ipv4_address
,
&
dl_teid
.
teid_gre_key
,
decoded_msg
->
dL_NGU_UP_TNLInformation
->
choice
.
gTPTunnel
->
gTP_TEID
.
buf
,
sizeof
(
struct
in_addr
));
memcpy
(
&
dl_teid
.
teid_gre_key
,
&
dl_teid
.
ipv4_address
,
decoded_msg
->
dL_NGU_UP_TNLInformation
->
choice
.
gTPTunnel
->
transportLayerAddress
.
buf
,
4
);
smreq
->
req
.
set_dl_fteid
(
dl_teid
);
Logger
::
smf_app
().
debug
(
"gTP_TEID "
"0x%"
PRIx32
" "
,
htonl
(
dl_teid
.
teid_gre_key
));
Logger
::
smf_app
().
debug
(
"uPTransportLayerInformation IP Addr %s"
,
conv
::
toString
(
dl_teid
.
ipv4_address
).
c_str
());
//list of Qos Flows which have been successfully setup or modified
for
(
int
i
=
0
;
i
<
decoded_msg
->
qosFlowAddOrModifyResponseList
->
list
.
count
;
i
++
)
{
smreq
->
req
.
add_qfi
(
(
decoded_msg
->
qosFlowAddOrModifyResponseList
->
list
.
array
[
i
])
->
qosFlowIdentifier
);
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: list of QoS Flows which have failed to be modified, qosFlowFailedToAddOrModifyList
//
TODO: additionalDLQosFlowPerTNLInformation
//need to update UPF accordingly
update_upf
=
true
;
...
...
@@ -2111,8 +2054,6 @@ void smf_context::handle_pdu_session_update_sm_context_request(
int
decode_status
=
smf_n1_n2_inst
.
decode_n2_sm_information
(
decoded_msg
,
n2_sm_information
);
if
(
decode_status
==
RETURNerror
)
{
Logger
::
smf_api_server
().
warn
(
"asn_decode failed"
);
//send error to AMF
Logger
::
smf_app
().
warn
(
"Decode N2 SM (Ngap_PDUSessionResourceReleaseResponseTransfer) failed!"
);
problem_details
.
setCause
(
...
...
@@ -2124,19 +2065,8 @@ void smf_context::handle_pdu_session_update_sm_context_request(
return
;
}
//don't need to create a procedure to update UPF
//Send ITTI to N11 to send PDUSession_UpdateSMContext Response to AMF
//No need to create N1/N2 Container
sm_context_resp_pending
->
session_procedure_type
=
procedure_type
;
Logger
::
smf_app
().
info
(
"Sending ITTI message %s to task TASK_SMF_N11"
,
sm_context_resp_pending
->
get_msg_name
());
int
ret
=
itti_inst
->
send_msg
(
sm_context_resp_pending
);
if
(
RETURNok
!=
ret
)
{
Logger
::
smf_app
().
error
(
"Could not send ITTI message %s to task TASK_SMF_N11"
,
sm_context_resp_pending
->
get_msg_name
());
}
//don't need to create a procedure to update UPF
}
break
;
...
...
@@ -2199,7 +2129,6 @@ void smf_context::handle_pdu_session_update_sm_context_request(
std
::
shared_ptr
<
smf_procedure
>
sproc
=
std
::
shared_ptr
<
smf_procedure
>
(
proc
);
proc
->
session_procedure_type
=
procedure_type
;
//smreq->req = sm_context_req_msg;
insert_procedure
(
sproc
);
if
(
proc
->
run
(
smreq
,
sm_context_resp_pending
,
shared_from_this
()))
{
// error !
...
...
@@ -2258,6 +2187,15 @@ void smf_context::handle_pdu_session_update_sm_context_request(
return
;
}
}
else
{
Logger
::
smf_app
().
info
(
"Sending ITTI message %s to task TASK_SMF_N11"
,
sm_context_resp_pending
->
get_msg_name
());
int
ret
=
itti_inst
->
send_msg
(
sm_context_resp_pending
);
if
(
RETURNok
!=
ret
)
{
Logger
::
smf_app
().
error
(
"Could not send ITTI message %s to task TASK_SMF_N11"
,
sm_context_resp_pending
->
get_msg_name
());
}
}
//TODO, Step 6
...
...
@@ -2269,7 +2207,6 @@ void smf_context::handle_pdu_session_update_sm_context_request(
}
//-------------------------------------------------------------------------------------
void
smf_context
::
handle_pdu_session_release_sm_context_request
(
std
::
shared_ptr
<
itti_n11_release_sm_context_request
>
smreq
)
{
...
...
@@ -2278,52 +2215,48 @@ void smf_context::handle_pdu_session_release_sm_context_request(
bool
update_upf
=
false
;
//Step 1. get DNN, SMF PDU session context. At this stage, dnn_context and pdu_session must be existed
std
::
shared_ptr
<
dnn_context
>
sd
=
{
};
std
::
shared_ptr
<
smf_pdu_session
>
sp
=
{
};
bool
find_dnn
=
find_dnn_context
(
smreq
->
req
.
get_snssai
(),
smreq
->
req
.
get_dnn
(),
sd
);
bool
find_pdu
=
false
;
if
(
find_dnn
)
{
find_pdu
=
sd
.
get
()
->
find_pdu_session
(
smreq
->
req
.
get_pdu_session_id
(),
sp
);
}
if
(
!
find_dnn
or
!
find_pdu
)
{
//error, send reply to AMF with error code "Context Not Found"
Logger
::
smf_app
().
warn
(
"DNN or PDU session context does not exist!"
);
smf_n11_inst
->
send_pdu_session_release_sm_context_response
(
smreq
->
http_response
,
Pistache
::
Http
::
Code
::
Not_Found
);
return
;
}
//we need to store HttpResponse and session-related information to be used when receiving the response from UPF
itti_n11_release_sm_context_response
*
n11_sm_context_resp
=
new
itti_n11_release_sm_context_response
(
TASK_SMF_APP
,
TASK_SMF_N11
,
//Step 1. get DNN, SMF PDU session context. At this stage, dnn_context and pdu_session must be existed
std
::
shared_ptr
<
dnn_context
>
sd
=
{
};
std
::
shared_ptr
<
smf_pdu_session
>
sp
=
{
};
bool
find_dnn
=
find_dnn_context
(
smreq
->
req
.
get_snssai
(),
smreq
->
req
.
get_dnn
(),
sd
);
bool
find_pdu
=
false
;
if
(
find_dnn
)
{
find_pdu
=
sd
.
get
()
->
find_pdu_session
(
smreq
->
req
.
get_pdu_session_id
(),
sp
);
}
if
(
!
find_dnn
or
!
find_pdu
)
{
//error, send reply to AMF with error code "Context Not Found"
Logger
::
smf_app
().
warn
(
"DNN or PDU session context does not exist!"
);
smf_n11_inst
->
send_pdu_session_release_sm_context_response
(
smreq
->
http_response
,
Pistache
::
Http
::
Code
::
Not_Found
);
return
;
}
//we need to store HttpResponse and session-related information to be used when receiving the response from UPF
itti_n11_release_sm_context_response
*
n11_sm_context_resp
=
new
itti_n11_release_sm_context_response
(
TASK_SMF_APP
,
TASK_SMF_N11
,
smreq
->
http_response
);
std
::
shared_ptr
<
itti_n11_release_sm_context_response
>
sm_context_resp_pending
=
std
::
shared_ptr
<
itti_n11_release_sm_context_response
>
(
n11_sm_context_resp
);
n11_sm_context_resp
->
res
.
set_supi
(
smreq
->
req
.
get_supi
());
n11_sm_context_resp
->
res
.
set_supi_prefix
(
smreq
->
req
.
get_supi_prefix
());
n11_sm_context_resp
->
res
.
set_cause
(
REQUEST_ACCEPTED
);
n11_sm_context_resp
->
res
.
set_pdu_session_id
(
smreq
->
req
.
get_pdu_session_id
());
n11_sm_context_resp
->
res
.
set_snssai
(
smreq
->
req
.
get_snssai
());
n11_sm_context_resp
->
res
.
set_dnn
(
smreq
->
req
.
get_dnn
());
session_release_sm_context_procedure
*
proc
=
new
session_release_sm_context_procedure
(
sp
);
std
::
shared_ptr
<
smf_procedure
>
sproc
=
std
::
shared_ptr
<
smf_procedure
>
(
proc
);
insert_procedure
(
sproc
);
if
(
proc
->
run
(
smreq
,
sm_context_resp_pending
,
shared_from_this
()))
{
// error !
Logger
::
smf_app
().
info
(
"PDU Release SM Context Request procedure failed"
);
}
std
::
shared_ptr
<
itti_n11_release_sm_context_response
>
sm_context_resp_pending
=
std
::
shared_ptr
<
itti_n11_release_sm_context_response
>
(
n11_sm_context_resp
);
n11_sm_context_resp
->
res
.
set_supi
(
smreq
->
req
.
get_supi
());
n11_sm_context_resp
->
res
.
set_supi_prefix
(
smreq
->
req
.
get_supi_prefix
());
n11_sm_context_resp
->
res
.
set_cause
(
REQUEST_ACCEPTED
);
n11_sm_context_resp
->
res
.
set_pdu_session_id
(
smreq
->
req
.
get_pdu_session_id
());
n11_sm_context_resp
->
res
.
set_snssai
(
smreq
->
req
.
get_snssai
());
n11_sm_context_resp
->
res
.
set_dnn
(
smreq
->
req
.
get_dnn
());
session_release_sm_context_procedure
*
proc
=
new
session_release_sm_context_procedure
(
sp
);
std
::
shared_ptr
<
smf_procedure
>
sproc
=
std
::
shared_ptr
<
smf_procedure
>
(
proc
);
insert_procedure
(
sproc
);
if
(
proc
->
run
(
smreq
,
sm_context_resp_pending
,
shared_from_this
()))
{
// error !
Logger
::
smf_app
().
info
(
"PDU Release SM Context Request procedure failed"
);
}
}
...
...
src/smf_app/smf_n1_n2.cpp
View file @
251022eb
...
...
@@ -57,6 +57,9 @@ extern "C" {
#include "Ngap_PDUSessionResourceReleaseCommandTransfer.h"
#include "dynamic_memory_check.h"
#include "Ngap_PDUSessionResourceReleaseResponseTransfer.h"
#include "Ngap_QosFlowAddOrModifyResponseItem.h"
#include "Ngap_QosFlowAddOrModifyResponseList.h"
}
#define BUF_LEN 512
...
...
@@ -1330,6 +1333,105 @@ void smf_n1_n2::create_n2_sm_information(pdu_session_msg &msg,
}
break
;
case
n2_sm_info_type_e
:
:
PDU_RES_MOD_RSP
:
{
//PDU Session Resource Modify Response Transfer IE
//for testing purpose
Logger
::
smf_app
().
debug
(
"[Create N2 SM Information] NGAP PDU Session Resource Modify Response Transfer"
);
//struct Ngap_UPTransportLayerInformation *dL_NGU_UP_TNLInformation; /* OPTIONAL */
//struct Ngap_UPTransportLayerInformation *uL_NGU_UP_TNLInformation; /* OPTIONAL */
//struct Ngap_QosFlowAddOrModifyResponseList *qosFlowAddOrModifyResponseList; /* OPTIONAL */
//struct Ngap_QosFlowPerTNLInformationList *additionalDLQosFlowPerTNLInformation; /* OPTIONAL */
// struct Ngap_QosFlowListWithCause *qosFlowFailedToAddOrModifyList; /* OPTIONAL */
Ngap_PDUSessionResourceModifyResponseTransfer_t
*
ngap_resource_response_transfer
=
nullptr
;
ngap_resource_response_transfer
=
(
Ngap_PDUSessionResourceModifyResponseTransfer_t
*
)
calloc
(
1
,
sizeof
(
Ngap_PDUSessionResourceModifyResponseTransfer_t
));
ngap_resource_response_transfer
->
dL_NGU_UP_TNLInformation
=
(
Ngap_UPTransportLayerInformation
*
)
calloc
(
1
,
sizeof
(
Ngap_UPTransportLayerInformation
));
ngap_resource_response_transfer
->
dL_NGU_UP_TNLInformation
->
present
=
Ngap_UPTransportLayerInformation_PR_gTPTunnel
;
ngap_resource_response_transfer
->
dL_NGU_UP_TNLInformation
->
choice
.
gTPTunnel
=
(
Ngap_GTPTunnel_t
*
)
calloc
(
1
,
sizeof
(
Ngap_GTPTunnel_t
));
ngap_resource_response_transfer
->
dL_NGU_UP_TNLInformation
->
choice
.
gTPTunnel
->
transportLayerAddress
.
size
=
4
;
ngap_resource_response_transfer
->
dL_NGU_UP_TNLInformation
->
choice
.
gTPTunnel
->
transportLayerAddress
.
buf
=
(
uint8_t
*
)
calloc
(
4
,
sizeof
(
uint8_t
));
ngap_resource_response_transfer
->
dL_NGU_UP_TNLInformation
->
choice
.
gTPTunnel
->
transportLayerAddress
.
buf
[
0
]
=
0xc0
;
ngap_resource_response_transfer
->
dL_NGU_UP_TNLInformation
->
choice
.
gTPTunnel
->
transportLayerAddress
.
buf
[
1
]
=
0xa8
;
ngap_resource_response_transfer
->
dL_NGU_UP_TNLInformation
->
choice
.
gTPTunnel
->
transportLayerAddress
.
buf
[
2
]
=
0xf8
;
ngap_resource_response_transfer
->
dL_NGU_UP_TNLInformation
->
choice
.
gTPTunnel
->
transportLayerAddress
.
buf
[
3
]
=
0x9f
;
ngap_resource_response_transfer
->
dL_NGU_UP_TNLInformation
->
choice
.
gTPTunnel
->
transportLayerAddress
.
bits_unused
=
0
;
ngap_resource_response_transfer
->
dL_NGU_UP_TNLInformation
->
choice
.
gTPTunnel
->
gTP_TEID
.
size
=
4
;
ngap_resource_response_transfer
->
dL_NGU_UP_TNLInformation
->
choice
.
gTPTunnel
->
gTP_TEID
.
buf
=
(
uint8_t
*
)
calloc
(
4
,
sizeof
(
uint8_t
));
ngap_resource_response_transfer
->
dL_NGU_UP_TNLInformation
->
choice
.
gTPTunnel
->
gTP_TEID
.
buf
[
0
]
=
0x00
;
ngap_resource_response_transfer
->
dL_NGU_UP_TNLInformation
->
choice
.
gTPTunnel
->
gTP_TEID
.
buf
[
1
]
=
0x00
;
ngap_resource_response_transfer
->
dL_NGU_UP_TNLInformation
->
choice
.
gTPTunnel
->
gTP_TEID
.
buf
[
2
]
=
0x00
;
ngap_resource_response_transfer
->
dL_NGU_UP_TNLInformation
->
choice
.
gTPTunnel
->
gTP_TEID
.
buf
[
3
]
=
0x01
;
ngap_resource_response_transfer
->
qosFlowAddOrModifyResponseList
=
(
Ngap_QosFlowAddOrModifyResponseList_t
*
)
calloc
(
1
,
sizeof
(
Ngap_QosFlowAddOrModifyResponseList_t
));
Ngap_QosFlowAddOrModifyResponseItem
*
qosFlowAddOrModifyResponseItem
=
nullptr
;
qosFlowAddOrModifyResponseItem
=
(
Ngap_QosFlowAddOrModifyResponseItem
*
)
calloc
(
1
,
sizeof
(
Ngap_QosFlowAddOrModifyResponseItem
));
qosFlowAddOrModifyResponseItem
->
qosFlowIdentifier
=
60
;
ASN_SEQUENCE_ADD
(
&
ngap_resource_response_transfer
->
qosFlowAddOrModifyResponseList
->
list
,
qosFlowAddOrModifyResponseItem
);
//encode
size_t
buffer_size
=
512
;
char
*
buffer
=
(
char
*
)
calloc
(
1
,
buffer_size
);
asn_enc_rval_t
er
=
aper_encode_to_buffer
(
&
asn_DEF_Ngap_PDUSessionResourceModifyResponseTransfer
,
nullptr
,
ngap_resource_response_transfer
,
(
void
*
)
buffer
,
buffer_size
);
if
(
er
.
encoded
<
0
)
{
Logger
::
smf_app
().
warn
(
"[Create N2 SM Information] NGAP PDU Session Resource Modify Response Transfer encode failed, er.encoded: %d"
,
er
.
encoded
);
return
;
}
Logger
::
smf_app
().
debug
(
"N2 SM buffer data: "
);
for
(
int
i
=
0
;
i
<
er
.
encoded
;
i
++
)
printf
(
"%02x "
,
(
char
)
buffer
[
i
]);
Logger
::
smf_app
().
debug
(
" (%d bytes)
\n
"
,
er
.
encoded
);
std
::
string
ngap_message
((
char
*
)
buffer
,
er
.
encoded
);
ngap_msg_str
=
ngap_message
;
//free memory
free_wrapper
(
(
void
**
)
&
ngap_resource_response_transfer
->
dL_NGU_UP_TNLInformation
->
choice
.
gTPTunnel
->
transportLayerAddress
.
buf
);
free_wrapper
(
(
void
**
)
&
ngap_resource_response_transfer
->
dL_NGU_UP_TNLInformation
->
choice
.
gTPTunnel
->
gTP_TEID
.
buf
);
free_wrapper
(
(
void
**
)
&
ngap_resource_response_transfer
->
dL_NGU_UP_TNLInformation
->
choice
.
gTPTunnel
);
free_wrapper
((
void
**
)
&
qosFlowAddOrModifyResponseItem
);
free_wrapper
((
void
**
)
&
ngap_resource_response_transfer
->
qosFlowAddOrModifyResponseList
);
free_wrapper
((
void
**
)
&
ngap_resource_response_transfer
);
free_wrapper
((
void
**
)
&
buffer
);
}
break
;
//PDU Session Resource Release Command Transfer
case
n2_sm_info_type_e
:
:
PDU_RES_REL_CMD
:
{
//PDU Session Resource Release Command Transfer IE
...
...
@@ -1513,7 +1615,7 @@ int smf_n1_n2::decode_n2_sm_information(
free_wrapper
((
void
**
)
&
data
);
if
(
rc
.
code
!=
RC_OK
)
{
Logger
::
smf_ap
i_server
().
warn
(
"asn_decode failed with code %d"
,
rc
.
code
);
Logger
::
smf_ap
p
().
warn
(
"asn_decode failed with code %d"
,
rc
.
code
);
return
RETURNerror
;
}
return
RETURNok
;
...
...
@@ -1542,7 +1644,7 @@ int smf_n1_n2::decode_n2_sm_information(
free_wrapper
((
void
**
)
&
data
);
if
(
rc
.
code
!=
RC_OK
)
{
Logger
::
smf_ap
i_server
().
warn
(
"asn_decode failed with code %d"
,
rc
.
code
);
Logger
::
smf_ap
p
().
warn
(
"asn_decode failed with code %d"
,
rc
.
code
);
return
RETURNerror
;
}
...
...
@@ -1572,7 +1674,7 @@ int smf_n1_n2::decode_n2_sm_information(
free_wrapper
((
void
**
)
&
data
);
if
(
rc
.
code
!=
RC_OK
)
{
Logger
::
smf_ap
i_server
().
warn
(
"asn_decode failed with code %d"
,
rc
.
code
);
Logger
::
smf_ap
p
().
warn
(
"asn_decode failed with code %d"
,
rc
.
code
);
return
RETURNerror
;
}
...
...
src/test/amf_client/amf-client.cpp
View file @
251022eb
...
...
@@ -290,10 +290,10 @@ void send_pdu_session_update_sm_context_establishment(
ENCODE_U8
(
buffer
,
0x00
,
size
);
ENCODE_U8
(
buffer
+
size
,
0x03
,
size
);
ENCODE_U8
(
buffer
+
size
,
0xe0
,
size
);
ENCODE_U8
(
buffer
+
size
,
0xac
,
size
);
//uPTransportLayerInformation IP Addr 172.1
0.5.1
: 172.
ENCODE_U8
(
buffer
+
size
,
0x
0a
,
size
);
//10
ENCODE_U8
(
buffer
+
size
,
0x0
5
,
size
);
//.5
ENCODE_U8
(
buffer
+
size
,
0x
01
,
size
);
//.1
ENCODE_U8
(
buffer
+
size
,
0xac
,
size
);
//uPTransportLayerInformation IP Addr 172.1
6.3.103
: 172.
ENCODE_U8
(
buffer
+
size
,
0x
10
,
size
);
//16
ENCODE_U8
(
buffer
+
size
,
0x0
3
,
size
);
//.3
ENCODE_U8
(
buffer
+
size
,
0x
67
,
size
);
//.103
ENCODE_U8
(
buffer
+
size
,
0x00
,
size
);
//gTP_TEID 00 00 00 01: 00
ENCODE_U8
(
buffer
+
size
,
0x00
,
size
);
//00
ENCODE_U8
(
buffer
+
size
,
0x00
,
size
);
//00
...
...
@@ -496,6 +496,207 @@ void send_pdu_session_modification_request_step1(std::string smf_ip_address) {
free
(
buffer
);
}
//------------------------------------------------------------------------------
void
send_pdu_session_modification_request_step2
(
std
::
string
smf_ip_address
)
{
std
::
cout
<<
"[AMF N11] PDU Session Modification procedure (SM Context Update, step 2)"
<<
std
::
endl
;
nlohmann
::
json
pdu_session_modification
;
//encode PDU Session Resource Modify Response Transfer IE
size_t
buffer_size
=
128
;
char
*
buffer
=
(
char
*
)
calloc
(
1
,
buffer_size
);
int
size
=
0
;
//ENCODE_U8(buffer, 0x00, size);
ENCODE_U8
(
buffer
+
size
,
0x50
,
size
);
ENCODE_U8
(
buffer
+
size
,
0x03
,
size
);
ENCODE_U8
(
buffer
+
size
,
0xe0
,
size
);
//Id dL_NGU_UP_TNLInformation
ENCODE_U8
(
buffer
+
size
,
0xac
,
size
);
//Transport Layer Address 172.16.3.101: 172
ENCODE_U8
(
buffer
+
size
,
0x10
,
size
);
//Transport Layer Address 172.16.3.101: 16
ENCODE_U8
(
buffer
+
size
,
0x03
,
size
);
//Transport Layer Address 172.16.3.101: 3
ENCODE_U8
(
buffer
+
size
,
0x65
,
size
);
//Transport Layer Address 172.16.3.101: 101
ENCODE_U8
(
buffer
+
size
,
0x00
,
size
);
//Gtp-teid: 01000000
ENCODE_U8
(
buffer
+
size
,
0x00
,
size
);
//Gtp-teid: 01000000
ENCODE_U8
(
buffer
+
size
,
0x00
,
size
);
//Gtp-teid: 01000000
ENCODE_U8
(
buffer
+
size
,
0x01
,
size
);
//Gtp-teid: 01000000
ENCODE_U8
(
buffer
+
size
,
0x00
,
size
);
//QoSFlowAddorModifyResponseList
ENCODE_U8
(
buffer
+
size
,
0x78
,
size
);
//60: QFI
/*
struct Ngap_UPTransportLayerInformation *dL_NGU_UP_TNLInformation;
struct Ngap_UPTransportLayerInformation *uL_NGU_UP_TNLInformation;
struct Ngap_QosFlowAddOrModifyResponseList *qosFlowAddOrModifyResponseList;
struct Ngap_QosFlowPerTNLInformationList *additionalDLQosFlowPerTNLInformation;
struct Ngap_QosFlowListWithCause *qosFlowFailedToAddOrModifyList;
struct Ngap_ProtocolExtensionContainer *iE_Extensions;
*/
std
::
cout
<<
"Buffer: "
<<
std
::
endl
;
for
(
int
i
=
0
;
i
<
size
;
i
++
)
{
printf
(
"%02x "
,
buffer
[
i
]);
}
std
::
cout
<<
"Buffer: "
<<
std
::
endl
;
std
::
string
url
=
std
::
string
(
"http://"
);
url
.
append
(
smf_ip_address
);
url
.
append
(
std
::
string
(
"/nsmf-pdusession/v2/sm-contexts/1/modify"
));
//Fill the json part
pdu_session_modification
[
"n2SmInfoType"
]
=
"PDU_RES_MOD_RSP"
;
//"PDU_RES_SETUP_RSP"
pdu_session_modification
[
"n2SmInfo"
][
"contentId"
]
=
"n2SmMsg"
;
//NGAP
std
::
string
body
;
std
::
string
boundary
=
"----Boundary"
;
std
::
string
json_part
=
pdu_session_modification
.
dump
();
std
::
string
n2_msg
(
reinterpret_cast
<
const
char
*>
(
buffer
),
size
);
create_multipart_related_content
(
body
,
json_part
,
boundary
,
n2_msg
,
multipart_related_content_part_e
::
NGAP
);
unsigned
char
*
data
=
(
unsigned
char
*
)
malloc
(
body
.
length
()
+
1
);
memset
(
data
,
0
,
body
.
length
()
+
1
);
memcpy
((
void
*
)
data
,
(
void
*
)
body
.
c_str
(),
body
.
length
());
curl_global_init
(
CURL_GLOBAL_ALL
);
CURL
*
curl
=
curl
=
curl_easy_init
();
if
(
curl
)
{
CURLcode
res
=
{
};
struct
curl_slist
*
headers
=
nullptr
;
//headers = curl_slist_append(headers, "charsets: utf-8");
headers
=
curl_slist_append
(
headers
,
"content-type: multipart/related; boundary=----Boundary"
);
curl_easy_setopt
(
curl
,
CURLOPT_HTTPHEADER
,
headers
);
curl_easy_setopt
(
curl
,
CURLOPT_URL
,
url
.
c_str
());
curl_easy_setopt
(
curl
,
CURLOPT_HTTPGET
,
1
);
curl_easy_setopt
(
curl
,
CURLOPT_TIMEOUT_MS
,
100L
);
//curl_easy_setopt(curl, CURLOPT_INTERFACE, "eno1:amf"); //hardcoded
// Response information.
long
httpCode
=
{
0
};
std
::
unique_ptr
<
std
::
string
>
httpData
(
new
std
::
string
());
curl_easy_setopt
(
curl
,
CURLOPT_WRITEFUNCTION
,
&
callback
);
curl_easy_setopt
(
curl
,
CURLOPT_WRITEDATA
,
httpData
.
get
());
curl_easy_setopt
(
curl
,
CURLOPT_POSTFIELDSIZE
,
body
.
length
());
curl_easy_setopt
(
curl
,
CURLOPT_POSTFIELDS
,
data
);
res
=
curl_easy_perform
(
curl
);
curl_easy_getinfo
(
curl
,
CURLINFO_RESPONSE_CODE
,
&
httpCode
);
//get cause from the response
nlohmann
::
json
response_data
;
try
{
response_data
=
nlohmann
::
json
::
parse
(
*
httpData
.
get
());
}
catch
(
nlohmann
::
json
::
exception
&
e
)
{
std
::
cout
<<
"Could not get json data from the response"
<<
std
::
endl
;
}
std
::
cout
<<
"[AMF N11] PDU Session Modification procedure (step 2), response from SMF, Http Code "
<<
httpCode
<<
std
::
endl
;
curl_easy_cleanup
(
curl
);
}
curl_global_cleanup
();
free
(
buffer
);
}
//------------------------------------------------------------------------------
void
send_pdu_session_modification_complete
(
std
::
string
smf_ip_address
)
{
std
::
cout
<<
"[AMF N11] PDU Session Modification Complete (Update SM Context): N1 SM - PDU Session Modification Complete"
<<
std
::
endl
;
nlohmann
::
json
pdu_session_modification_complete
;
//encode PDU Session Modification Complete
size_t
buffer_size
=
128
;
char
*
buffer
=
(
char
*
)
calloc
(
1
,
buffer_size
);
int
size
=
0
;
ENCODE_U8
(
buffer
,
0x2e
,
size
);
//ExtendedProtocolDiscriminator
ENCODE_U8
(
buffer
+
size
,
0x01
,
size
);
//PDUSessionIdentity
ENCODE_U8
(
buffer
+
size
,
0x01
,
size
);
//ProcedureTransactionIdentity
ENCODE_U8
(
buffer
+
size
,
0xcc
,
size
);
//MessageType
ENCODE_U8
(
buffer
+
size
,
0x00
,
size
);
//presence
ENCODE_U8
(
buffer
+
size
,
0x00
,
size
);
//Extended protocol configuration options
std
::
cout
<<
"Buffer: "
<<
std
::
endl
;
for
(
int
i
=
0
;
i
<
size
;
i
++
)
{
printf
(
"%02x "
,
buffer
[
i
]);
}
std
::
cout
<<
"Buffer: "
<<
std
::
endl
;
std
::
string
url
=
std
::
string
(
"http://"
);
url
.
append
(
smf_ip_address
);
url
.
append
(
std
::
string
(
"/nsmf-pdusession/v2/sm-contexts/1/modify"
));
//Fill the json part
pdu_session_modification_complete
[
"n1SmMsg"
][
"contentId"
]
=
"n1SmMsg"
;
// NAS
std
::
string
body
;
std
::
string
boundary
=
"----Boundary"
;
std
::
string
json_part
=
pdu_session_modification_complete
.
dump
();
std
::
string
n1_msg
(
reinterpret_cast
<
const
char
*>
(
buffer
),
size
);
create_multipart_related_content
(
body
,
json_part
,
boundary
,
n1_msg
,
multipart_related_content_part_e
::
NAS
);
unsigned
char
*
data
=
(
unsigned
char
*
)
malloc
(
body
.
length
()
+
1
);
memset
(
data
,
0
,
body
.
length
()
+
1
);
memcpy
((
void
*
)
data
,
(
void
*
)
body
.
c_str
(),
body
.
length
());
curl_global_init
(
CURL_GLOBAL_ALL
);
CURL
*
curl
=
curl
=
curl_easy_init
();
if
(
curl
)
{
CURLcode
res
=
{
};
struct
curl_slist
*
headers
=
nullptr
;
//headers = curl_slist_append(headers, "charsets: utf-8");
headers
=
curl_slist_append
(
headers
,
"content-type: multipart/related; boundary=----Boundary"
);
curl_easy_setopt
(
curl
,
CURLOPT_HTTPHEADER
,
headers
);
curl_easy_setopt
(
curl
,
CURLOPT_URL
,
url
.
c_str
());
curl_easy_setopt
(
curl
,
CURLOPT_HTTPGET
,
1
);
curl_easy_setopt
(
curl
,
CURLOPT_TIMEOUT_MS
,
100L
);
//curl_easy_setopt(curl, CURLOPT_INTERFACE, "eno1:amf"); //hardcoded
// Response information.
long
httpCode
=
{
0
};
std
::
unique_ptr
<
std
::
string
>
httpData
(
new
std
::
string
());
curl_easy_setopt
(
curl
,
CURLOPT_WRITEFUNCTION
,
&
callback
);
curl_easy_setopt
(
curl
,
CURLOPT_WRITEDATA
,
httpData
.
get
());
curl_easy_setopt
(
curl
,
CURLOPT_POSTFIELDSIZE
,
body
.
length
());
curl_easy_setopt
(
curl
,
CURLOPT_POSTFIELDS
,
data
);
res
=
curl_easy_perform
(
curl
);
curl_easy_getinfo
(
curl
,
CURLINFO_RESPONSE_CODE
,
&
httpCode
);
//get cause from the response
nlohmann
::
json
response_data
;
try
{
response_data
=
nlohmann
::
json
::
parse
(
*
httpData
.
get
());
}
catch
(
nlohmann
::
json
::
exception
&
e
)
{
std
::
cout
<<
"Could not get json data from the response"
<<
std
::
endl
;
}
std
::
cout
<<
"[AMF N11] PDU Session Modification Complete, response from SMF, Http Code "
<<
httpCode
<<
std
::
endl
;
curl_easy_cleanup
(
curl
);
}
curl_global_cleanup
();
free
(
buffer
);
}
//------------------------------------------------------------------------------
void
send_pdu_session_release_request
(
std
::
string
smf_ip_address
)
{
...
...
@@ -1054,6 +1255,9 @@ int main(int argc, char *argv[]) {
usleep
(
200000
);
//PDU Session Modification
send_pdu_session_modification_request_step1
(
smf_ip_address
);
send_pdu_session_modification_request_step2
(
smf_ip_address
);
send_pdu_session_modification_complete
(
smf_ip_address
);
//PDU Session Release procedure
send_pdu_session_release_request
(
smf_ip_address
);
usleep
(
200000
);
...
...
@@ -1063,7 +1267,7 @@ int main(int argc, char *argv[]) {
usleep
(
200000
);
//Release SM context
send_release_sm_context_request
(
smf_ip_address
);
//
send_release_sm_context_request(smf_ip_address);
return
0
;
}
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