Add PDU Session Release [#488]

This commit is contained in:
Sukchan Lee 2020-07-02 01:50:23 -04:00
parent 8afc4b7887
commit d9743286c5
53 changed files with 1734 additions and 214 deletions

View File

@ -61,6 +61,13 @@ typedef struct ogs_pfcp_xact_s {
uint8_t holding_rcount;
void *assoc_xact; /**< Associated GTP transaction */
#define OGS_PFCP_5GC_DELETE_TRIGGER_UE_REQUESTED 1
#define OGS_PFCP_5GC_DELETE_TRIGGER_PCF_INITIATED 2
#define OGS_PFCP_5GC_DELETE_TRIGGER_RAN_INITIATED 3
#define OGS_PFCP_5GC_DELETE_TRIGGER_SMF_INITIATED 4
#define OGS_PFCP_5GC_DELETE_TRIGGER_AMF_RELEASE_SM_CONTEXT 5
#define OGS_PFCP_5GC_DELETE_TRIGGER_AMF_UPDATE_SM_CONTEXT 6
int trigger;
} ogs_pfcp_xact_t;
int ogs_pfcp_xact_init(ogs_timer_mgr_t *timer_mgr, int size);

View File

@ -133,6 +133,9 @@ void ogs_sbi_message_free(ogs_sbi_message_t *message)
if (message->N1N2MessageTransferRspData)
OpenAPI_n1_n2_message_transfer_rsp_data_free(
message->N1N2MessageTransferRspData);
if (message->SmContextStatusNotification)
OpenAPI_sm_context_status_notification_free(
message->SmContextStatusNotification);
for (i = 0; i < message->num_of_part; i++) {
if (message->part[i].pkbuf)
@ -709,6 +712,10 @@ static char *build_json(ogs_sbi_message_t *message)
item = OpenAPI_n1_n2_message_transfer_rsp_data_convertToJSON(
message->N1N2MessageTransferRspData);
ogs_assert(item);
} else if (message->SmContextStatusNotification) {
item = OpenAPI_sm_context_status_notification_convertToJSON(
message->SmContextStatusNotification);
ogs_assert(item);
}
if (item) {
@ -1234,6 +1241,23 @@ static int parse_json(ogs_sbi_message_t *message,
message->h.resource.component[0]);
END
break;
CASE(OGS_SBI_SERVICE_NAME_NAMF_CALLBACK)
SWITCH(message->h.resource.component[1])
CASE(OGS_SBI_RESOURCE_NAME_SM_CONTEXT_STATUS)
message->SmContextStatusNotification =
OpenAPI_sm_context_status_notification_parseFromJSON(item);
if (!message->SmContextStatusNotification) {
rv = OGS_ERROR;
ogs_error("JSON parse error");
}
break;
DEFAULT
rv = OGS_ERROR;
ogs_error("Unknown resource name [%s]",
message->h.resource.component[1]);
END
break;
DEFAULT
rv = OGS_ERROR;

View File

@ -252,6 +252,7 @@ typedef struct ogs_sbi_message_s {
SessionManagementSubscriptionData;
OpenAPI_n1_n2_message_transfer_req_data_t *N1N2MessageTransferReqData;
OpenAPI_n1_n2_message_transfer_rsp_data_t *N1N2MessageTransferRspData;
OpenAPI_sm_context_status_notification_t *SmContextStatusNotification;
ogs_sbi_links_t *links;

View File

@ -58,6 +58,7 @@
#include "model/session_management_subscription_data.h"
#include "model/n1_n2_message_transfer_req_data.h"
#include "model/n1_n2_message_transfer_rsp_data.h"
#include "model/sm_context_status_notification.h"
#include "custom/links.h"

View File

@ -229,6 +229,23 @@ void amf_state_operational(ogs_fsm_t *s, amf_event_t *e)
END
break;
CASE(OGS_SBI_SERVICE_NAME_NAMF_CALLBACK)
SWITCH(sbi_message.h.resource.component[1])
CASE(OGS_SBI_RESOURCE_NAME_SM_CONTEXT_STATUS)
amf_namf_callback_handle_sm_context_status(
session, &sbi_message);
break;
DEFAULT
ogs_error("Invalid resource name [%s]",
sbi_message.h.resource.component[1]);
ogs_sbi_server_send_error(session,
OGS_SBI_HTTP_STATUS_BAD_REQUEST, &sbi_message,
"Invalid resource name",
sbi_message.h.resource.component[1]);
END
break;
DEFAULT
ogs_error("Invalid API name [%s]", sbi_message.h.service.name);
ogs_sbi_server_send_error(session,

View File

@ -403,7 +403,6 @@ typedef struct amf_sess_s {
/* SMF session context is activated or not */
OpenAPI_up_cnx_state_e smfUpCnxState;
OpenAPI_n2_sm_info_type_e n2SmInfoType;
ogs_pkbuf_t *n2smbuf;
/* last payload for sending back to the UE */

View File

@ -773,14 +773,16 @@ int gmm_handle_security_mode_complete(amf_ue_t *amf_ue,
int gmm_handle_ul_nas_transport(amf_ue_t *amf_ue,
ogs_nas_5gs_ul_nas_transport_t *ul_nas_transport)
{
amf_sess_t *sess = NULL;
amf_nsmf_pdu_session_update_sm_context_param_t param;
ogs_nas_payload_container_type_t *payload_container_type = NULL;
ogs_nas_payload_container_t *payload_container = NULL;
ogs_nas_pdu_session_identity_2_t *pdu_session_id = NULL;
ogs_nas_s_nssai_t *nas_s_nssai = NULL;
ogs_s_nssai_t *selected_s_nssai = NULL;
ogs_nas_dnn_t *dnn = NULL;
amf_sess_t *sess = NULL;
ogs_nas_5gsm_header_t *gsm_header = NULL;
ogs_assert(amf_ue);
ogs_assert(ul_nas_transport);
@ -792,16 +794,22 @@ int gmm_handle_ul_nas_transport(amf_ue_t *amf_ue,
if (!payload_container_type->value) {
ogs_error("[%s] No Payload container type", amf_ue->supi);
nas_5gs_send_gmm_status(
amf_ue, OGS_5GMM_CAUSE_INVALID_MANDATORY_INFORMATION);
return OGS_ERROR;
}
if (!payload_container->length) {
ogs_error("[%s] No Payload container length", amf_ue->supi);
nas_5gs_send_gmm_status(
amf_ue, OGS_5GMM_CAUSE_INVALID_MANDATORY_INFORMATION);
return OGS_ERROR;
}
if (!payload_container->buffer) {
ogs_error("[%s] No Payload container buffer", amf_ue->supi);
nas_5gs_send_gmm_status(
amf_ue, OGS_5GMM_CAUSE_INVALID_MANDATORY_INFORMATION);
return OGS_ERROR;
}
@ -814,9 +822,14 @@ int gmm_handle_ul_nas_transport(amf_ue_t *amf_ue,
dnn = &ul_nas_transport->dnn;
ogs_assert(dnn);
gsm_header = (ogs_nas_5gsm_header_t *)payload_container->buffer;
ogs_assert(gsm_header);
if ((ul_nas_transport->presencemask &
OGS_NAS_5GS_UL_NAS_TRANSPORT_PDU_SESSION_ID_PRESENT) == 0) {
ogs_error("[%s] No PDU session ID", amf_ue->supi);
nas_5gs_send_gmm_status(
amf_ue, OGS_5GMM_CAUSE_INVALID_MANDATORY_INFORMATION);
return OGS_ERROR;
}
@ -824,6 +837,8 @@ int gmm_handle_ul_nas_transport(amf_ue_t *amf_ue,
if (*pdu_session_id == OGS_NAS_PDU_SESSION_IDENTITY_UNASSIGNED) {
ogs_error("[%s] PDU session identity is unassigned",
amf_ue->supi);
nas_5gs_send_gmm_status(
amf_ue, OGS_5GMM_CAUSE_INVALID_MANDATORY_INFORMATION);
return OGS_ERROR;
}
@ -872,18 +887,42 @@ int gmm_handle_ul_nas_transport(amf_ue_t *amf_ue,
if (ul_nas_transport->presencemask &
OGS_NAS_5GS_UL_NAS_TRANSPORT_DNN_PRESENT) {
if (sess->dnn)
ogs_free(dnn);
ogs_free(sess->dnn);
sess->dnn = ogs_strdup(dnn->value);
}
amf_sess_sbi_discover_and_send(
OpenAPI_nf_type_SMF, sess, NULL,
amf_nsmf_pdu_session_build_create_sm_context);
if (gsm_header->message_type ==
OGS_NAS_5GS_PDU_SESSION_ESTABLISHMENT_REQUEST) {
amf_sess_sbi_discover_and_send(
OpenAPI_nf_type_SMF, sess, NULL,
amf_nsmf_pdu_session_build_create_sm_context);
} else {
if (!SESSION_CONTEXT_IN_SMF(sess)) {
ogs_error("[%s] Session Context is not in SMF [%d]",
amf_ue->supi, sess->psi);
nas_5gs_send_back_5gsm_message(sess,
OGS_5GSM_CAUSE_PDU_SESSION_DOES_NOT_EXIST);
return OGS_ERROR;
}
memset(&param, 0, sizeof(param));
param.n1smbuf = sess->payload_container;
amf_sess_sbi_discover_and_send(
OpenAPI_nf_type_SMF, sess, &param,
amf_nsmf_pdu_session_build_update_sm_context);
}
break;
default:
ogs_error("[%s] Unknown Payload container type [%d]",
amf_ue->supi, payload_container_type->value);
nas_5gs_send_gmm_status(amf_ue,
OGS_5GMM_CAUSE_MESSAGE_TYPE_NON_EXISTENT_OR_NOT_IMPLEMENTED);
return OGS_ERROR;
}

View File

@ -299,12 +299,8 @@ static void common_register_state(ogs_fsm_t *s, amf_event_t *e)
break;
case OGS_NAS_5GS_UL_NAS_TRANSPORT:
rv = gmm_handle_ul_nas_transport(
gmm_handle_ul_nas_transport(
amf_ue, &nas_message->gmm.ul_nas_transport);
if (rv != OGS_OK) {
nas_5gs_send_gmm_status(
amf_ue, OGS_5GMM_CAUSE_INVALID_MANDATORY_INFORMATION);
}
break;
default:

View File

@ -158,3 +158,84 @@ int amf_namf_comm_handle_n1_n2_message_transfer(
return OGS_OK;
}
int amf_namf_callback_handle_sm_context_status(
ogs_sbi_session_t *session, ogs_sbi_message_t *recvmsg)
{
int status = OGS_SBI_HTTP_STATUS_NO_CONTENT;
amf_ue_t *amf_ue = NULL;
amf_sess_t *sess = NULL;
uint8_t pdu_session_identity;
ogs_sbi_message_t sendmsg;
ogs_sbi_response_t *response = NULL;
OpenAPI_sm_context_status_notification_t *SmContextStatusNotification;
OpenAPI_status_info_t *StatusInfo;
ogs_assert(session);
ogs_assert(recvmsg);
if (!recvmsg->h.resource.component[0]) {
status = OGS_SBI_HTTP_STATUS_BAD_REQUEST;
ogs_error("No SUPI");
goto cleanup;
}
amf_ue = amf_ue_find_by_supi(recvmsg->h.resource.component[0]);
if (!amf_ue) {
status = OGS_SBI_HTTP_STATUS_NOT_FOUND;
ogs_error("Cannot find SUPI [%s]", recvmsg->h.resource.component[0]);
goto cleanup;
}
if (!recvmsg->h.resource.component[2]) {
status = OGS_SBI_HTTP_STATUS_BAD_REQUEST;
ogs_error("[%s] No PDU Session Identity", amf_ue->supi);
goto cleanup;
}
pdu_session_identity = atoi(recvmsg->h.resource.component[2]);
if (pdu_session_identity == OGS_NAS_PDU_SESSION_IDENTITY_UNASSIGNED) {
status = OGS_SBI_HTTP_STATUS_BAD_REQUEST;
ogs_error("[%s] PDU Session Identity is unassigned", amf_ue->supi);
goto cleanup;
}
sess = amf_sess_find_by_psi(amf_ue, pdu_session_identity);
if (!sess) {
status = OGS_SBI_HTTP_STATUS_NOT_FOUND;
ogs_error("[%s] Cannot find session [%d]", amf_ue->supi, sess->psi);
goto cleanup;
}
SmContextStatusNotification = recvmsg->SmContextStatusNotification;
if (!SmContextStatusNotification) {
status = OGS_SBI_HTTP_STATUS_BAD_REQUEST;
ogs_error("No SmContextStatusNotification");
goto cleanup;
}
StatusInfo = SmContextStatusNotification->status_info;
if (!StatusInfo) {
status = OGS_SBI_HTTP_STATUS_BAD_REQUEST;
ogs_error("No StatusInfo");
goto cleanup;
}
if (StatusInfo->resource_status == OpenAPI_resource_status_RELEASED) {
ogs_info("[%s:%d] Session Released", amf_ue->supi, sess->psi);
amf_sess_remove(sess);
}
cleanup:
memset(&sendmsg, 0, sizeof(sendmsg));
response = ogs_sbi_build_response(&sendmsg, status);
ogs_assert(response);
ogs_sbi_server_send_response(session, response);
return OGS_OK;
}

View File

@ -28,6 +28,8 @@ extern "C" {
int amf_namf_comm_handle_n1_n2_message_transfer(
ogs_sbi_session_t *session, ogs_sbi_message_t *recvmsg);
int amf_namf_callback_handle_sm_context_status(
ogs_sbi_session_t *session, ogs_sbi_message_t *recvmsg);
#ifdef __cplusplus
}

View File

@ -328,6 +328,34 @@ void nas_send_pdu_session_establishment_accept(amf_sess_t *sess,
ogs_expect(rv == OGS_OK);
}
void nas_send_pdu_session_release_command(amf_sess_t *sess,
ogs_pkbuf_t *n1smbuf, ogs_pkbuf_t *n2smbuf)
{
int rv;
amf_ue_t *amf_ue = NULL;
ogs_pkbuf_t *gmmbuf = NULL;
ogs_pkbuf_t *ngapbuf = NULL;
ogs_assert(sess);
amf_ue = sess->amf_ue;
ogs_assert(amf_ue);
ogs_assert(n1smbuf);
ogs_assert(n2smbuf);
gmmbuf = gmm_build_dl_nas_transport(sess,
OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, n1smbuf, 0, 0);
ogs_expect_or_return(gmmbuf);
ngapbuf = ngap_build_pdu_session_resource_release_command(
sess, gmmbuf, n2smbuf);
ogs_expect_or_return(ngapbuf);
rv = nas_5gs_send_to_gnb(amf_ue, ngapbuf);
ogs_expect(rv == OGS_OK);
}
void nas_5gs_send_gmm_status(amf_ue_t *amf_ue, ogs_nas_5gmm_cause_t cause)
{
int rv;

View File

@ -56,6 +56,8 @@ void nas_5gs_send_configuration_update_command(
void nas_send_pdu_session_establishment_accept(amf_sess_t *sess,
ogs_pkbuf_t *n1smbuf, ogs_pkbuf_t *n2smbuf);
void nas_send_pdu_session_release_command(amf_sess_t *sess,
ogs_pkbuf_t *n1smbuf, ogs_pkbuf_t *n2smbuf);
void nas_5gs_send_gmm_status(amf_ue_t *amf_ue, ogs_nas_5gmm_cause_t cause);

View File

@ -909,6 +909,113 @@ ogs_pkbuf_t *ngap_build_pdu_session_resource_setup_request(
return nga_ngap_encode(&pdu);
}
ogs_pkbuf_t *ngap_build_pdu_session_resource_release_command(
amf_sess_t *sess, ogs_pkbuf_t *gmmbuf, ogs_pkbuf_t *n2smbuf)
{
amf_ue_t *amf_ue = NULL;
ran_ue_t *ran_ue = NULL;
NGAP_NGAP_PDU_t pdu;
NGAP_InitiatingMessage_t *initiatingMessage = NULL;
NGAP_PDUSessionResourceReleaseCommand_t *PDUSessionResourceReleaseCommand;
NGAP_PDUSessionResourceReleaseCommandIEs_t *ie = NULL;
NGAP_AMF_UE_NGAP_ID_t *AMF_UE_NGAP_ID = NULL;
NGAP_RAN_UE_NGAP_ID_t *RAN_UE_NGAP_ID = NULL;
NGAP_NAS_PDU_t *NAS_PDU = NULL;
NGAP_PDUSessionResourceToReleaseListRelCmd_t *PDUSessionList = NULL;
NGAP_PDUSessionResourceToReleaseItemRelCmd_t *PDUSessionItem = NULL;
OCTET_STRING_t *transfer = NULL;
ogs_assert(gmmbuf);
ogs_assert(n2smbuf);
ogs_assert(sess);
amf_ue = sess->amf_ue;
ogs_assert(amf_ue);
ran_ue = amf_ue->ran_ue;
ogs_assert(ran_ue);
memset(&pdu, 0, sizeof (NGAP_NGAP_PDU_t));
pdu.present = NGAP_NGAP_PDU_PR_initiatingMessage;
pdu.choice.initiatingMessage = CALLOC(1, sizeof(NGAP_InitiatingMessage_t));
initiatingMessage = pdu.choice.initiatingMessage;
initiatingMessage->procedureCode =
NGAP_ProcedureCode_id_PDUSessionResourceRelease;
initiatingMessage->criticality = NGAP_Criticality_reject;
initiatingMessage->value.present =
NGAP_InitiatingMessage__value_PR_PDUSessionResourceReleaseCommand;
PDUSessionResourceReleaseCommand =
&initiatingMessage->value.choice.PDUSessionResourceReleaseCommand;
ie = CALLOC(1, sizeof(NGAP_PDUSessionResourceReleaseCommandIEs_t));
ASN_SEQUENCE_ADD(&PDUSessionResourceReleaseCommand->protocolIEs, ie);
ie->id = NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID;
ie->criticality = NGAP_Criticality_reject;
ie->value.present =
NGAP_PDUSessionResourceReleaseCommandIEs__value_PR_AMF_UE_NGAP_ID;
AMF_UE_NGAP_ID = &ie->value.choice.AMF_UE_NGAP_ID;
ie = CALLOC(1, sizeof(NGAP_PDUSessionResourceReleaseCommandIEs_t));
ASN_SEQUENCE_ADD(&PDUSessionResourceReleaseCommand->protocolIEs, ie);
ie->id = NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID;
ie->criticality = NGAP_Criticality_reject;
ie->value.present =
NGAP_PDUSessionResourceReleaseCommandIEs__value_PR_RAN_UE_NGAP_ID;
RAN_UE_NGAP_ID = &ie->value.choice.RAN_UE_NGAP_ID;
ie = CALLOC(1, sizeof(NGAP_PDUSessionResourceReleaseCommandIEs_t));
ASN_SEQUENCE_ADD(&PDUSessionResourceReleaseCommand->protocolIEs, ie);
ie->id = NGAP_ProtocolIE_ID_id_NAS_PDU;
ie->criticality = NGAP_Criticality_ignore;
ie->value.present =
NGAP_PDUSessionResourceReleaseCommandIEs__value_PR_NAS_PDU;
NAS_PDU = &ie->value.choice.NAS_PDU;
ie = CALLOC(1, sizeof(NGAP_PDUSessionResourceReleaseCommandIEs_t));
ASN_SEQUENCE_ADD(&PDUSessionResourceReleaseCommand->protocolIEs, ie);
ie->id = NGAP_ProtocolIE_ID_id_PDUSessionResourceToReleaseListRelCmd;
ie->criticality = NGAP_Criticality_reject;
ie->value.present = NGAP_PDUSessionResourceReleaseCommandIEs__value_PR_PDUSessionResourceToReleaseListRelCmd;
PDUSessionList = &ie->value.choice.PDUSessionResourceToReleaseListRelCmd;
ogs_debug(" RAN_UE_NGAP_ID[%d] AMF_UE_NGAP_ID[%lld]",
ran_ue->ran_ue_ngap_id, (long long)ran_ue->amf_ue_ngap_id);
asn_uint642INTEGER(AMF_UE_NGAP_ID, ran_ue->amf_ue_ngap_id);
*RAN_UE_NGAP_ID = ran_ue->ran_ue_ngap_id;
NAS_PDU->size = gmmbuf->len;
NAS_PDU->buf = CALLOC(NAS_PDU->size, sizeof(uint8_t));
memcpy(NAS_PDU->buf, gmmbuf->data, NAS_PDU->size);
ogs_pkbuf_free(gmmbuf);
PDUSessionItem =
CALLOC(1, sizeof(struct NGAP_PDUSessionResourceToReleaseItemRelCmd));
ASN_SEQUENCE_ADD(&PDUSessionList->list, PDUSessionItem);
PDUSessionItem->pDUSessionID = sess->psi;
transfer = &PDUSessionItem->pDUSessionResourceReleaseCommandTransfer;
transfer->size = n2smbuf->len;
transfer->buf = CALLOC(transfer->size, sizeof(uint8_t));
memcpy(transfer->buf, n2smbuf->data, transfer->size);
ogs_pkbuf_free(n2smbuf);
return nga_ngap_encode(&pdu);
}
#if 0
ogs_pkbuf_t *ngap_build_paging(
amf_ue_t *amf_ue, NGAP_CNDomain_t cn_domain)

View File

@ -41,10 +41,8 @@ ogs_pkbuf_t *ngap_build_ue_context_release_command(
ogs_pkbuf_t *ngap_build_pdu_session_resource_setup_request(
amf_sess_t *sess, ogs_pkbuf_t *gmmbuf, ogs_pkbuf_t *n2smbuf);
ogs_pkbuf_t *ngap_build_e_rab_modify_request(
amf_bearer_t *bearer, ogs_pkbuf_t *gsmbuf);
ogs_pkbuf_t *ngap_build_e_rab_release_command(
amf_bearer_t *bearer, ogs_pkbuf_t *gsmbuf, NGAP_Cause_PR group, long cause);
ogs_pkbuf_t *ngap_build_pdu_session_resource_release_command(
amf_sess_t *sess, ogs_pkbuf_t *gmmbuf, ogs_pkbuf_t *n2smbuf);
#if 0
ogs_pkbuf_t *ngap_build_paging(

View File

@ -771,6 +771,7 @@ void ngap_handle_initial_context_setup_response(
memset(&param, 0, sizeof(param));
param.n2smbuf = ogs_pkbuf_alloc(NULL, OGS_MAX_SDU_LEN);
param.n2SmInfoType = OpenAPI_n2_sm_info_type_PDU_RES_SETUP_RSP;
ogs_pkbuf_put_data(param.n2smbuf, transfer->buf, transfer->size);
amf_sess_sbi_discover_and_send(
@ -1412,6 +1413,164 @@ void ngap_handle_pdu_session_resource_setup_response(
memset(&param, 0, sizeof(param));
param.n2smbuf = ogs_pkbuf_alloc(NULL, OGS_MAX_SDU_LEN);
param.n2SmInfoType = OpenAPI_n2_sm_info_type_PDU_RES_SETUP_RSP;
ogs_pkbuf_put_data(param.n2smbuf, transfer->buf, transfer->size);
amf_sess_sbi_discover_and_send(
OpenAPI_nf_type_SMF, sess, &param,
amf_nsmf_pdu_session_build_update_sm_context);
ogs_pkbuf_free(param.n2smbuf);
}
}
void ngap_handle_pdu_session_resource_release_response(
amf_gnb_t *gnb, ogs_ngap_message_t *message)
{
char buf[OGS_ADDRSTRLEN];
int i;
amf_ue_t *amf_ue = NULL;
ran_ue_t *ran_ue = NULL;
uint64_t amf_ue_ngap_id;
amf_nsmf_pdu_session_update_sm_context_param_t param;
NGAP_SuccessfulOutcome_t *successfulOutcome = NULL;
NGAP_PDUSessionResourceReleaseResponse_t *PDUSessionResourceReleaseResponse;
NGAP_PDUSessionResourceReleaseResponseIEs_t *ie = NULL;
NGAP_AMF_UE_NGAP_ID_t *AMF_UE_NGAP_ID = NULL;
NGAP_PDUSessionResourceReleasedListRelRes_t *PDUSessionList = NULL;
NGAP_PDUSessionResourceReleasedItemRelRes_t *PDUSessionItem = NULL;
OCTET_STRING_t *transfer = NULL;
ogs_assert(gnb);
ogs_assert(gnb->sock);
ogs_assert(message);
successfulOutcome = message->choice.successfulOutcome;
ogs_assert(successfulOutcome);
PDUSessionResourceReleaseResponse =
&successfulOutcome->value.choice.PDUSessionResourceReleaseResponse;
ogs_assert(PDUSessionResourceReleaseResponse);
ogs_debug("PDU session resource release response");
for (i = 0; i < PDUSessionResourceReleaseResponse->protocolIEs.list.count;
i++) {
ie = PDUSessionResourceReleaseResponse->protocolIEs.list.array[i];
switch (ie->id) {
case NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID:
AMF_UE_NGAP_ID = &ie->value.choice.AMF_UE_NGAP_ID;
break;
case NGAP_ProtocolIE_ID_id_PDUSessionResourceReleasedListRelRes:
PDUSessionList =
&ie->value.choice.PDUSessionResourceReleasedListRelRes;
break;
default:
break;
}
}
ogs_debug(" IP[%s] RAN_ID[%d]", OGS_ADDR(gnb->addr, buf), gnb->gnb_id);
if (!AMF_UE_NGAP_ID) {
ogs_error("No AMF_UE_NGAP_ID");
ngap_send_error_indication(gnb, NULL, NULL,
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
return;
}
if (asn_INTEGER2ulong(AMF_UE_NGAP_ID,
(unsigned long *)&amf_ue_ngap_id) != 0) {
ogs_error("Invalid AMF_UE_NGAP_ID");
ngap_send_error_indication(gnb, NULL, NULL,
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
return;
}
ran_ue = ran_ue_find_by_amf_ue_ngap_id(amf_ue_ngap_id);
if (!ran_ue) {
ogs_error("No RAN UE Context : AMF_UE_NGAP_ID[%lld]",
(long long)amf_ue_ngap_id);
ngap_send_error_indication(
gnb, &ran_ue->ran_ue_ngap_id, &ran_ue->amf_ue_ngap_id,
NGAP_Cause_PR_radioNetwork,
NGAP_CauseRadioNetwork_unknown_local_UE_NGAP_ID);
return;
}
ogs_debug(" RAN_UE_NGAP_ID[%d] AMF_UE_NGAP_ID[%lld]",
ran_ue->ran_ue_ngap_id, (long long)ran_ue->amf_ue_ngap_id);
amf_ue = ran_ue->amf_ue;
if (!amf_ue) {
ogs_error("Cannot find AMF-UE Context [%lld]",
(long long)amf_ue_ngap_id);
ngap_send_error_indication(
gnb, &ran_ue->ran_ue_ngap_id, &ran_ue->amf_ue_ngap_id,
NGAP_Cause_PR_radioNetwork,
NGAP_CauseRadioNetwork_unknown_local_UE_NGAP_ID);
return;
}
if (!PDUSessionList) {
ogs_error("No PDUSessionResourceReleasedListRelRes");
ngap_send_error_indication2(amf_ue,
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
return;
}
for (i = 0; i < PDUSessionList->list.count; i++) {
amf_sess_t *sess = NULL;
PDUSessionItem = (NGAP_PDUSessionResourceReleasedItemRelRes_t *)
PDUSessionList->list.array[i];
if (!PDUSessionItem) {
ogs_error("No PDUSessionResourceReleasedItemRelRes");
ngap_send_error_indication2(amf_ue,
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
return;
}
transfer = &PDUSessionItem->pDUSessionResourceReleaseResponseTransfer;
if (!transfer) {
ogs_error("No PDUSessionResourceReleaseResponseTransfer");
ngap_send_error_indication2(amf_ue,
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
return;
}
if (PDUSessionItem->pDUSessionID ==
OGS_NAS_PDU_SESSION_IDENTITY_UNASSIGNED) {
ogs_error("PDU Session Identity is unassigned");
ngap_send_error_indication2(amf_ue,
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
return;
}
sess = amf_sess_find_by_psi(amf_ue, PDUSessionItem->pDUSessionID);
if (!sess) {
ogs_error("Cannot find PDU Session ID [%d]",
(int)PDUSessionItem->pDUSessionID);
ngap_send_error_indication2(amf_ue,
NGAP_Cause_PR_radioNetwork,
NGAP_CauseRadioNetwork_unknown_PDU_session_ID);
return;
}
if (!SESSION_CONTEXT_IN_SMF(sess)) {
ogs_error("Session Context is not in SMF [%d]",
(int)PDUSessionItem->pDUSessionID);
ngap_send_error_indication2(amf_ue,
NGAP_Cause_PR_radioNetwork,
NGAP_CauseRadioNetwork_unknown_PDU_session_ID);
return;
}
memset(&param, 0, sizeof(param));
param.n2smbuf = ogs_pkbuf_alloc(NULL, OGS_MAX_SDU_LEN);
param.n2SmInfoType = OpenAPI_n2_sm_info_type_PDU_RES_REL_RSP;
ogs_pkbuf_put_data(param.n2smbuf, transfer->buf, transfer->size);
amf_sess_sbi_discover_and_send(

View File

@ -41,6 +41,8 @@ void ngap_handle_initial_context_setup_failure(
void ngap_handle_pdu_session_resource_setup_response(
amf_gnb_t *gnb, ogs_ngap_message_t *message);
void ngap_handle_pdu_session_resource_release_response(
amf_gnb_t *gnb, ogs_ngap_message_t *message);
void ngap_handle_ue_context_modification_response(
amf_gnb_t *gnb, ogs_ngap_message_t *message);

View File

@ -130,6 +130,9 @@ void ngap_state_operational(ogs_fsm_t *s, amf_event_t *e)
case NGAP_ProcedureCode_id_PDUSessionResourceSetup:
ngap_handle_pdu_session_resource_setup_response(gnb, pdu);
break;
case NGAP_ProcedureCode_id_PDUSessionResourceRelease:
ngap_handle_pdu_session_resource_release_response(gnb, pdu);
break;
#if 0
case NGAP_ProcedureCode_id_UEContextModification:
ngap_handle_ue_context_modification_response(gnb, pdu);

View File

@ -34,7 +34,7 @@ ogs_sbi_request_t *amf_nsmf_pdu_session_build_create_sm_context(
OpenAPI_sm_context_create_data_t SmContextCreateData;
OpenAPI_plmn_id_nid_t plmn_id_nid;
OpenAPI_snssai_t s_nssai;
OpenAPI_ref_to_binary_data_t n1_sm_msg;
OpenAPI_ref_to_binary_data_t n1SmMsg;
OpenAPI_guami_t guami;
ogs_assert(sess);
@ -94,8 +94,8 @@ ogs_sbi_request_t *amf_nsmf_pdu_session_build_create_sm_context(
SmContextCreateData.sm_context_status_uri =
ogs_sbi_server_uri(server, &header);
n1_sm_msg.content_id = (char *)OGS_SBI_CONTENT_5GNAS_SM_ID;
SmContextCreateData.n1_sm_msg = &n1_sm_msg;
n1SmMsg.content_id = (char *)OGS_SBI_CONTENT_5GNAS_SM_ID;
SmContextCreateData.n1_sm_msg = &n1SmMsg;
message.SmContextCreateData = &SmContextCreateData;
@ -134,6 +134,7 @@ ogs_sbi_request_t *amf_nsmf_pdu_session_build_update_sm_context(
ogs_sbi_request_t *request = NULL;
OpenAPI_sm_context_update_data_t SmContextUpdateData;
OpenAPI_ref_to_binary_data_t n1SmMsg;
OpenAPI_ref_to_binary_data_t n2SmInfo;
OpenAPI_ng_ap_cause_t ngApCause;
@ -150,29 +151,43 @@ ogs_sbi_request_t *amf_nsmf_pdu_session_build_update_sm_context(
message.h.resource.component[1] = sess->sm_context_ref;
message.h.resource.component[2] = (char *)OGS_SBI_RESOURCE_NAME_MODIFY;
memset(&SmContextUpdateData, 0, sizeof(SmContextUpdateData));
message.num_of_part = 0;
if (param->n1smbuf) {
n1SmMsg.content_id = (char *)OGS_SBI_CONTENT_5GNAS_SM_ID;
SmContextUpdateData.n1_sm_msg = &n1SmMsg;
message.part[message.num_of_part].pkbuf = param->n1smbuf;
message.part[message.num_of_part].content_id =
(char *)OGS_SBI_CONTENT_5GNAS_SM_ID;
message.part[message.num_of_part].content_type =
(char *)OGS_SBI_CONTENT_5GNAS_TYPE;
message.num_of_part++;
message.SmContextUpdateData = &SmContextUpdateData;
}
if (param->n2smbuf) {
memset(&SmContextUpdateData, 0, sizeof(SmContextUpdateData));
SmContextUpdateData.n2_sm_info_type =
OpenAPI_n2_sm_info_type_PDU_RES_SETUP_RSP;
ogs_assert(param->n2SmInfoType);
SmContextUpdateData.n2_sm_info_type = param->n2SmInfoType;
SmContextUpdateData.n2_sm_info = &n2SmInfo;
memset(&n2SmInfo, 0, sizeof(n2SmInfo));
n2SmInfo.content_id = (char *)OGS_SBI_CONTENT_NGAP_SM_ID;
message.part[message.num_of_part].pkbuf = param->n2smbuf;
if (message.part[message.num_of_part].pkbuf) {
message.part[message.num_of_part].content_id =
(char *)OGS_SBI_CONTENT_NGAP_SM_ID;
message.part[message.num_of_part].content_type =
(char *)OGS_SBI_CONTENT_NGAP_TYPE;
message.num_of_part++;
}
message.part[message.num_of_part].content_id =
(char *)OGS_SBI_CONTENT_NGAP_SM_ID;
message.part[message.num_of_part].content_type =
(char *)OGS_SBI_CONTENT_NGAP_TYPE;
message.num_of_part++;
message.SmContextUpdateData = &SmContextUpdateData;
}
if (param->upCnxState) {
memset(&SmContextUpdateData, 0, sizeof(SmContextUpdateData));
SmContextUpdateData.up_cnx_state = param->upCnxState;
if (param->ngApCause.group) {

View File

@ -27,7 +27,9 @@ extern "C" {
#endif
typedef struct amf_nsmf_pdu_session_update_sm_context_param_s {
ogs_pkbuf_t *n1smbuf;
ogs_pkbuf_t *n2smbuf;
OpenAPI_n2_sm_info_type_e n2SmInfoType;
OpenAPI_up_cnx_state_e upCnxState;
struct {
int group;

View File

@ -90,30 +90,28 @@ int amf_nsmf_pdu_session_handle_create_sm_context(
nas_5gs_send_back_5gsm_message_from_sbi(sess, recvmsg->res_status);
return OGS_ERROR;
}
n1SmMsg = SmContextCreateError->n1_sm_msg;
if (!n1SmMsg || !n1SmMsg->content_id) {
ogs_error("[%d:%d] No N1 SM Message", sess->psi, sess->pti);
nas_5gs_send_back_5gsm_message_from_sbi(sess, recvmsg->res_status);
return OGS_ERROR;
if (n1SmMsg && n1SmMsg->content_id) {
n1smbuf = ogs_sbi_find_part_by_content_id(
recvmsg, n1SmMsg->content_id);
if (n1smbuf) {
/*
* NOTE : The pkbuf created in the SBI message will be removed
* from ogs_sbi_message_free(), so it must be copied.
*/
n1smbuf = ogs_pkbuf_copy(n1smbuf);
ogs_assert(n1smbuf);
nas_5gs_send_gsm_reject_from_sbi(sess,
OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION,
n1smbuf, recvmsg->res_status);
return OGS_ERROR;
}
}
n1smbuf = ogs_sbi_find_part_by_content_id(recvmsg, n1SmMsg->content_id);
if (!n1smbuf) {
ogs_error("[%d:%d] No N1 SM Content [%s]",
sess->psi, sess->pti, n1SmMsg->content_id);
nas_5gs_send_back_5gsm_message_from_sbi(sess, recvmsg->res_status);
return OGS_ERROR;
}
nas_5gs_send_back_5gsm_message_from_sbi(sess, recvmsg->res_status);
/*
* NOTE : The pkbuf created in the SBI message will be removed
* from ogs_sbi_message_free(), so it must be copied.
*/
n1smbuf = ogs_pkbuf_copy(n1smbuf);
ogs_assert(n1smbuf);
nas_5gs_send_gsm_reject_from_sbi(sess,
OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION,
n1smbuf, recvmsg->res_status);
return OGS_ERROR;
}
return OGS_OK;
@ -130,134 +128,167 @@ int amf_nsmf_pdu_session_handle_update_sm_context(
if (recvmsg->res_status == OGS_SBI_HTTP_STATUS_NO_CONTENT ||
recvmsg->res_status == OGS_SBI_HTTP_STATUS_OK) {
if (recvmsg->res_status == OGS_SBI_HTTP_STATUS_OK) {
/* Nothing */
}
OpenAPI_sm_context_updated_data_t *SmContextUpdatedData = NULL;
OpenAPI_ref_to_binary_data_t *n1SmMsg = NULL;
OpenAPI_ref_to_binary_data_t *n2SmInfo = NULL;
ogs_pkbuf_t *n1smbuf = NULL;
ogs_pkbuf_t *n2smbuf = NULL;
/* UPDATE_UpCnxState - SYNC */
sess->smfUpCnxState = sess->ueUpCnxState;
if (sess->ueUpCnxState == OpenAPI_up_cnx_state_ACTIVATED) {
/*
* 1. PDUSessionResourceSetupResponse
* 2. /nsmf-pdusession/v1/sm-contexts/{smContextRef}/modify
* 3. PFCP Session Modifcation Request (OuterHeaderCreation)
* 4. PFCP Session Modifcation Response
*/
/*
* 1. InitialContextSetupResponse
* 2. /nsmf-pdusession/v1/sm-contexts/{smContextRef}/modify
* 3. PFCP Session Modifcation Request (Apply: FORWARD)
* 4. PFCP Session Modifcation Response
*/
/* Nothing */
} else if (sess->ueUpCnxState == OpenAPI_up_cnx_state_DEACTIVATED) {
/*
* 1. UEContextReleaseRequest
* 2. /nsmf-pdusession/v1/sm-contexts/{smContextRef}/modify
* 3. PFCP Session Modifcation Request (Apply:Buff & NOCP)
* 4. PFCP Session Modifcation Response
* 5. UEContextReleaseCommand
* 6. UEContextReleaseComplete
*/
if (SESSION_SYNC_DONE(amf_ue)) {
ngap_send_amf_ue_context_release_command(amf_ue,
NGAP_Cause_PR_nas, NGAP_CauseNas_normal_release,
NGAP_UE_CTX_REL_NG_CONTEXT_REMOVE, 0);
}
} else if (sess->ueUpCnxState == OpenAPI_up_cnx_state_ACTIVATING) {
OpenAPI_sm_context_updated_data_t *SmContextUpdatedData = NULL;
OpenAPI_ref_to_binary_data_t *n2SmInfo = NULL;
ogs_pkbuf_t *n2smbuf = NULL;
/*
* 1. ServiceRequest
* 2. /nsmf-pdusession/v1/sm-contexts/{smContextRef}/modify
*/
if (recvmsg->SmContextUpdatedData &&
recvmsg->SmContextUpdatedData->n2_sm_info) {
SmContextUpdatedData = recvmsg->SmContextUpdatedData;
if (!SmContextUpdatedData) {
ogs_error("No SmContextUpdatedData");
nas_5gs_send_gmm_reject(amf_ue,
OGS_5GMM_CAUSE_5GS_SERVICES_NOT_ALLOWED);
return OGS_ERROR;
}
ogs_assert(SmContextUpdatedData);
n2SmInfo = SmContextUpdatedData->n2_sm_info;
if (!n2SmInfo || !n2SmInfo->content_id) {
ogs_error("No SmInfo");
nas_5gs_send_gmm_reject(amf_ue,
OGS_5GMM_CAUSE_5GS_SERVICES_NOT_ALLOWED);
return OGS_ERROR;
ogs_assert(n2SmInfo);
if (n2SmInfo->content_id) {
n2smbuf = ogs_sbi_find_part_by_content_id(
recvmsg, n2SmInfo->content_id);
}
sess->n2SmInfoType = SmContextUpdatedData->n2_sm_info_type;
if (!sess->n2SmInfoType) {
ogs_error("No SmInfoType");
nas_5gs_send_gmm_reject(amf_ue,
OGS_5GMM_CAUSE_5GS_SERVICES_NOT_ALLOWED);
return OGS_ERROR;
n1SmMsg = SmContextUpdatedData->n1_sm_msg;
if (n1SmMsg && n1SmMsg->content_id) {
n1smbuf = ogs_sbi_find_part_by_content_id(
recvmsg, n1SmMsg->content_id);
}
n2smbuf = ogs_sbi_find_part_by_content_id(
recvmsg, n2SmInfo->content_id);
if (!n2smbuf) {
ogs_error("[%s] No N2 SM Content", amf_ue->supi);
nas_5gs_send_gmm_reject(amf_ue,
OGS_5GMM_CAUSE_5GS_SERVICES_NOT_ALLOWED);
return OGS_ERROR;
}
switch (SmContextUpdatedData->n2_sm_info_type) {
case OpenAPI_n2_sm_info_type_PDU_RES_SETUP_REQ:
if (!n2smbuf) {
ogs_error("[%s:%d] No N2 SM Content",
amf_ue->supi, sess->psi);
nas_5gs_send_gmm_reject(amf_ue,
OGS_5GMM_CAUSE_5GS_SERVICES_NOT_ALLOWED);
return OGS_ERROR;
}
/*
* To Deliver N2 SM Content to gNB Temporarily,
* Store N2 SM Context in Session Context
*/
if (sess->n2smbuf) {
/*
* It should not be reached this way.
* If the problem occurred, free the old n2smbuf
* To Deliver N2 SM Content to gNB Temporarily,
* Store N2 SM Context in Session Context
*/
ogs_error("N2 SM Content is duplicated");
ogs_pkbuf_free(sess->n2smbuf);
}
/*
* NOTE : The pkbuf created in the SBI message will be removed
* from ogs_sbi_message_free().
* So it must be copied and push a event queue.
*/
sess->n2smbuf = ogs_pkbuf_copy(n2smbuf);
ogs_assert(sess->n2smbuf);
if (sess->n2smbuf) {
/*
* It should not be reached this way.
* If the problem occurred, free the old n2smbuf
*/
ogs_error("[%s:%d] N2 SM Content is duplicated",
amf_ue->supi, sess->psi);
ogs_pkbuf_free(sess->n2smbuf);
}
/*
* NOTE : The pkbuf created in the SBI message will be removed
* from ogs_sbi_message_free().
* So it must be copied and push a event queue.
*/
sess->n2smbuf = ogs_pkbuf_copy(n2smbuf);
ogs_assert(sess->n2smbuf);
if (SESSION_SYNC_DONE(amf_ue)) {
nas_5gs_send_accept(amf_ue);
if (SESSION_SYNC_DONE(amf_ue)) {
nas_5gs_send_accept(amf_ue);
/*
* After sending accept message, N2 SM context is freed
* For checking memory, NULL pointer should be set to n2smbuf.
*/
ogs_list_for_each(&amf_ue->sess_list, sess) {
if (sess->n2smbuf) {
ogs_pkbuf_free(sess->n2smbuf);
sess->n2smbuf = NULL;
ogs_list_for_each(&amf_ue->sess_list, sess) {
if (sess->n2smbuf) {
ogs_pkbuf_free(sess->n2smbuf);
sess->n2smbuf = NULL;
}
}
}
break;
case OpenAPI_n2_sm_info_type_PDU_RES_REL_CMD:
if (!n1smbuf) {
ogs_error("[%s:%d] No N1 SM Content [%s]",
amf_ue->supi, sess->psi, n1SmMsg->content_id);
nas_5gs_send_back_5gsm_message(sess,
OGS_5GSM_CAUSE_SEMANTICALLY_INCORRECT_MESSAGE);
return OGS_ERROR;
}
/*
* NOTE : The pkbuf created in the SBI message will be removed
* from ogs_sbi_message_free(), so it must be copied.
*/
n1smbuf = ogs_pkbuf_copy(n1smbuf);
ogs_assert(n1smbuf);
n2smbuf = ogs_pkbuf_copy(n2smbuf);
ogs_assert(n2smbuf);
nas_send_pdu_session_release_command(sess, n1smbuf, n2smbuf);
break;
default:
ogs_error("Not implemented [%d]",
SmContextUpdatedData->n2_sm_info_type);
ngap_send_error_indication2(amf_ue,
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
}
} else {
ogs_error("Invalid UpCnxState [UE:%d,SMF:%d]",
sess->ueUpCnxState, sess->smfUpCnxState);
}
if (sess->ueUpCnxState == OpenAPI_up_cnx_state_ACTIVATED) {
/*
* 1. PDUSessionResourceSetupResponse
* 2. /nsmf-pdusession/v1/sm-contexts/{smContextRef}/modify
* 3. PFCP Session Modifcation Request (OuterHeaderCreation)
* 4. PFCP Session Modifcation Response
*/
/*
* 1. InitialContextSetupResponse
* 2. /nsmf-pdusession/v1/sm-contexts/{smContextRef}/modify
* 3. PFCP Session Modifcation Request (Apply: FORWARD)
* 4. PFCP Session Modifcation Response
*/
/*
* 1. PDUSessionResourceReleaseResponse
* 2. /nsmf-pdusession/v1/sm-contexts/{smContextRef}/modify
*/
/* Nothing */
} else if (sess->ueUpCnxState == OpenAPI_up_cnx_state_DEACTIVATED) {
/*
* 1. UEContextReleaseRequest
* 2. /nsmf-pdusession/v1/sm-contexts/{smContextRef}/modify
* 3. PFCP Session Modifcation Request (Apply:Buff & NOCP)
* 4. PFCP Session Modifcation Response
* 5. UEContextReleaseCommand
* 6. UEContextReleaseComplete
*/
if (SESSION_SYNC_DONE(amf_ue)) {
ngap_send_amf_ue_context_release_command(amf_ue,
NGAP_Cause_PR_nas, NGAP_CauseNas_normal_release,
NGAP_UE_CTX_REL_NG_CONTEXT_REMOVE, 0);
}
} else if (sess->ueUpCnxState == OpenAPI_up_cnx_state_ACTIVATING) {
/* Not reached here */
} else {
ogs_error("Invalid UpCnxState [UE:%d,SMF:%d]",
sess->ueUpCnxState, sess->smfUpCnxState);
}
}
} else {
amf_ue_t *amf_ue = NULL;
OpenAPI_sm_context_update_error_t *SmContextUpdateError = NULL;
OpenAPI_ref_to_binary_data_t *n1SmMsg = NULL;
ogs_pkbuf_t *n1smbuf = NULL;
#if 0 /* Is it needed? */
OpenAPI_ref_to_binary_data_t *n2SmInfo = NULL;
ogs_pkbuf_t *n2smbuf = NULL;
@ -279,6 +310,25 @@ int amf_nsmf_pdu_session_handle_update_sm_context(
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
return OGS_ERROR;
}
n1SmMsg = SmContextUpdateError->n1_sm_msg;
if (n1SmMsg && n1SmMsg->content_id) {
n1smbuf = ogs_sbi_find_part_by_content_id(
recvmsg, n1SmMsg->content_id);
if (n1smbuf) {
/*
* NOTE : The pkbuf created in the SBI message will be removed
* from ogs_sbi_message_free(), so it must be copied.
*/
n1smbuf = ogs_pkbuf_copy(n1smbuf);
ogs_assert(n1smbuf);
nas_5gs_send_gsm_reject_from_sbi(sess,
OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION,
n1smbuf, recvmsg->res_status);
return OGS_ERROR;
}
}
#if 0 /* Is it needed? */
n2SmInfo = SmContextUpdateError->n2_sm_info;
if (!n2SmInfo || !n2SmInfo->content_id) {
@ -301,6 +351,8 @@ int amf_nsmf_pdu_session_handle_update_sm_context(
ngap_send_error_indication2(amf_ue,
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
return OGS_ERROR;
}
return OGS_OK;

View File

@ -190,16 +190,13 @@ void amf_sbi_send_deactivate_session(
/* UPDATE_UpCnxState - DEACTIVATED */
sess->ueUpCnxState = OpenAPI_up_cnx_state_DEACTIVATED;
if (sess->smfUpCnxState != OpenAPI_up_cnx_state_DEACTIVATED) {
memset(&param, 0, sizeof(param));
param.upCnxState = sess->ueUpCnxState;
param.ngApCause.group = group;
param.ngApCause.value = cause;
amf_sess_sbi_discover_and_send(
OpenAPI_nf_type_SMF, sess, &param,
amf_nsmf_pdu_session_build_update_sm_context);
}
memset(&param, 0, sizeof(param));
param.upCnxState = sess->ueUpCnxState;
param.ngApCause.group = group;
param.ngApCause.value = cause;
amf_sess_sbi_discover_and_send(
OpenAPI_nf_type_SMF, sess, &param,
amf_nsmf_pdu_session_build_update_sm_context);
}
void amf_sbi_send_deactivate_all_sessions(

View File

@ -238,6 +238,34 @@ ogs_pkbuf_t *emm_build_security_mode_command(mme_ue_t *mme_ue)
*replayed_ue_additional_security_capability =
&security_mode_command->replayed_ue_additional_security_capability;
#if 0
char *_reg = (char *)
"0741720bf632f540 800101dde9c6cf07 f0f0c04001001000 230201d031271d80"
"8021100101001081 0600000000830600 000000000300000a 00000d005232f540"
"00015c20001332f5 40000111034f1880 5d0105e010028dc0 6f04f000f000";
uint8_t tmp[OGS_MAX_SDU_LEN];
uint8_t s[OGS_MAX_SDU_LEN];
uint16_t len;
uint8_t key[32];
uint8_t output[OGS_SHA256_DIGEST_SIZE];
OGS_HEX(_reg, strlen(_reg), tmp);
len = htobe16(94);
memcpy(&s[94], &len, sizeof(len));
memset(key, 0, 32);
ogs_log_hexdump(OGS_LOG_FATAL, s, 96);
ogs_log_hexdump(OGS_LOG_FATAL, key, 32);
ogs_hmac_sha256(key, 32, s, 94, output, OGS_SHA256_DIGEST_SIZE);
ogs_log_hexdump(OGS_LOG_FATAL, output, 32);
memcpy(s, key, 32);
memcpy(s+32, tmp, 94);
ogs_sha256(s, 32+94, output);
ogs_log_hexdump(OGS_LOG_FATAL, output, 32);
#endif
ogs_assert(mme_ue);
memset(&message, 0, sizeof(message));

View File

@ -266,6 +266,7 @@ void mme_state_operational(ogs_fsm_t *s, mme_event_t *e)
ogs_assert(enb_ue);
pkbuf = e->pkbuf;
ogs_assert(pkbuf);
if (ogs_nas_emm_decode(&nas_message, pkbuf) != OGS_OK) {
ogs_error("ogs_nas_emm_decode() failed");
ogs_pkbuf_free(pkbuf);

View File

@ -49,12 +49,9 @@ static int client_notify_cb(ogs_sbi_response_t *response, void *data)
{
int rv;
ogs_sbi_client_t *client = NULL;
ogs_sbi_message_t message;
ogs_assert(response);
client = data;
ogs_assert(client);
rv = ogs_sbi_parse_response(&message, response);
if (rv != OGS_OK) {
@ -99,7 +96,7 @@ void nrf_nnrf_nfm_send_nf_status_notify(ogs_sbi_subscription_t *subscription,
request = nrf_nnrf_nfm_build_nf_status_notify(
client, subscription, event, nf_instance);
ogs_assert(request);
ogs_sbi_client_send_request(client, request, client);
ogs_sbi_client_send_request(client, request, NULL);
ogs_sbi_request_free(request);
}

View File

@ -1329,6 +1329,11 @@ void smf_sess_remove(smf_sess_t *sess)
if (sess->sm_context_ref)
ogs_free(sess->sm_context_ref);
if (sess->sm_context_status_uri)
ogs_free(sess->sm_context_status_uri);
if (sess->namf.client)
ogs_sbi_client_remove(sess->namf.client);
if (sess->dnn)
ogs_free(sess->dnn);

View File

@ -166,6 +166,11 @@ typedef struct smf_sess_s {
uint8_t psi; /* PDU session identity */
uint8_t pti; /* Procedure transaction identity */
char *sm_context_status_uri; /* SmContextStatusNotification */
struct {
ogs_sbi_client_t *client;
} namf;
/* PLMN ID & NID */
ogs_plmn_id_t plmn_id;
char *nid;

View File

@ -215,3 +215,41 @@ ogs_pkbuf_t *gsm_build_pdu_session_establishment_reject(
return ogs_nas_5gs_plain_encode(&message);
}
ogs_pkbuf_t *gsm_build_pdu_session_release_command(
smf_sess_t *sess, ogs_nas_5gsm_cause_t gsm_cause)
{
ogs_nas_5gs_message_t message;
ogs_nas_5gs_pdu_session_release_command_t *pdu_session_release_command =
&message.gsm.pdu_session_release_command;
memset(&message, 0, sizeof(message));
message.gsm.h.extended_protocol_discriminator =
OGS_NAS_EXTENDED_PROTOCOL_DISCRIMINATOR_5GSM;
message.gsm.h.pdu_session_identity = sess->psi;
message.gsm.h.procedure_transaction_identity = sess->pti;
message.gsm.h.message_type = OGS_NAS_5GS_PDU_SESSION_RELEASE_COMMAND;
pdu_session_release_command->gsm_cause = gsm_cause;
return ogs_nas_5gs_plain_encode(&message);
}
ogs_pkbuf_t *gsm_build_pdu_session_release_reject(
smf_sess_t *sess, ogs_nas_5gsm_cause_t gsm_cause)
{
ogs_nas_5gs_message_t message;
ogs_nas_5gs_pdu_session_release_reject_t *
pdu_session_release_reject = &message.gsm.pdu_session_release_reject;
memset(&message, 0, sizeof(message));
message.gsm.h.extended_protocol_discriminator =
OGS_NAS_EXTENDED_PROTOCOL_DISCRIMINATOR_5GSM;
message.gsm.h.pdu_session_identity = sess->psi;
message.gsm.h.procedure_transaction_identity = sess->pti;
message.gsm.h.message_type = OGS_NAS_5GS_PDU_SESSION_RELEASE_REJECT;
pdu_session_release_reject->gsm_cause = gsm_cause;
return ogs_nas_5gs_plain_encode(&message);
}

View File

@ -30,6 +30,11 @@ ogs_pkbuf_t *gsm_build_pdu_session_establishment_accept(smf_sess_t *sess);
ogs_pkbuf_t *gsm_build_pdu_session_establishment_reject(
smf_sess_t *sess, ogs_nas_5gsm_cause_t gsm_cause);
ogs_pkbuf_t *gsm_build_pdu_session_release_command(
smf_sess_t *sess, ogs_nas_5gsm_cause_t gsm_cause);
ogs_pkbuf_t *gsm_build_pdu_session_release_reject(
smf_sess_t *sess, ogs_nas_5gsm_cause_t gsm_cause);
ogs_pkbuf_t *gsm_build_status(smf_sess_t *sess, ogs_nas_5gsm_cause_t cause);
#ifdef __cplusplus

View File

@ -19,6 +19,7 @@
#include "gsm-handler.h"
#include "sbi-path.h"
#include "pfcp-path.h"
#undef OGS_LOG_DOMAIN
#define OGS_LOG_DOMAIN __gsm_log_domain
@ -64,7 +65,6 @@ int gsm_handle_pdu_session_establishment_request(smf_sess_t *sess,
extended_protocol_configuration_options);
}
smf_sbi_discover_and_send(OpenAPI_nf_type_UDM, sess,
(char *)OGS_SBI_RESOURCE_NAME_SM_DATA, smf_nudm_sdm_build_get);

View File

@ -39,6 +39,7 @@ void smf_gsm_state_final(ogs_fsm_t *s, smf_event_t *e)
void smf_gsm_state_operational(ogs_fsm_t *s, smf_event_t *e)
{
int rv;
char *strerror = NULL;
smf_ue_t *smf_ue = NULL;
smf_sess_t *sess = NULL;
ogs_pkbuf_t *pkbuf = NULL;
@ -169,6 +170,8 @@ void smf_gsm_state_operational(ogs_fsm_t *s, smf_event_t *e)
ogs_assert(nas_message);
sess = e->sess;
ogs_assert(sess);
session = sess->sbi.session;
ogs_assert(session);
smf_ue = sess->smf_ue;
ogs_assert(smf_ue);
@ -180,11 +183,29 @@ void smf_gsm_state_operational(ogs_fsm_t *s, smf_event_t *e)
ogs_error("[%s:%d] Cannot handle NAS message",
smf_ue->supi, sess->psi);
OGS_FSM_TRAN(s, smf_gsm_state_exception);
break;
}
break;
case OGS_NAS_5GS_PDU_SESSION_RELEASE_REQUEST:
smf_5gc_pfcp_send_session_deletion_request(
sess, OGS_PFCP_5GC_DELETE_TRIGGER_UE_REQUESTED);
break;
case OGS_NAS_5GS_PDU_SESSION_RELEASE_COMPLETE:
smf_sbi_send_response(sess, OGS_SBI_HTTP_STATUS_NO_CONTENT);
smf_sbi_send_sm_context_status_notify(sess);
OGS_FSM_TRAN(s, smf_gsm_state_released);
break;
default:
ogs_error("Unknown message[%d]", nas_message->gsm.h.message_type);
strerror = ogs_msprintf("Unknown message [%d]",
nas_message->gsm.h.message_type);
ogs_assert(strerror);
ogs_error("%s", strerror);
ogs_sbi_server_send_error(session,
OGS_SBI_HTTP_STATUS_BAD_REQUEST, NULL, strerror, NULL);
ogs_free(strerror);
break;
}
@ -210,6 +231,10 @@ void smf_gsm_state_operational(ogs_fsm_t *s, smf_event_t *e)
}
break;
case OpenAPI_n2_sm_info_type_PDU_RES_REL_RSP:
smf_sbi_send_response(sess, OGS_SBI_HTTP_STATUS_NO_CONTENT);
break;
default:
ogs_error("Unknown message[%d]", e->ngap.type);
}
@ -222,6 +247,31 @@ void smf_gsm_state_operational(ogs_fsm_t *s, smf_event_t *e)
}
}
void smf_gsm_state_released(ogs_fsm_t *s, smf_event_t *e)
{
smf_sess_t *sess = NULL;
ogs_assert(s);
ogs_assert(e);
smf_sm_debug(e);
sess = e->sess;
ogs_assert(sess);
switch (e->id) {
case OGS_FSM_ENTRY_SIG:
break;
case OGS_FSM_EXIT_SIG:
break;
default:
ogs_error("[%s] Unknown event %s",
sess->imsi_bcd, smf_event_get_name(e));
break;
}
}
void smf_gsm_state_exception(ogs_fsm_t *s, smf_event_t *e)
{
smf_sess_t *sess = NULL;
@ -241,7 +291,8 @@ void smf_gsm_state_exception(ogs_fsm_t *s, smf_event_t *e)
break;
default:
ogs_error("[%s] Unknown event %s", sess->imsi_bcd, smf_event_get_name(e));
ogs_error("[%s] Unknown event %s",
sess->imsi_bcd, smf_event_get_name(e));
break;
}
}

View File

@ -48,6 +48,7 @@ libsmf_sources = files('''
nnrf-handler.h
nudm-build.h
nudm-handler.h
nsmf-handler.h
namf-build.h
sbi-path.h
gsm-build.h

View File

@ -206,7 +206,8 @@ void smf_5gc_n4_handle_session_modification_response(
"PFCP Cause[%d] : No Accepted", rsp->cause.u8);
ogs_error("%s", strerror);
smf_sbi_send_sm_context_update_error(session,
OGS_SBI_HTTP_STATUS_BAD_REQUEST, strerror, NULL, NULL);
OGS_SBI_HTTP_STATUS_BAD_REQUEST, strerror,
NULL, NULL, NULL);
ogs_free(strerror);
return;
}
@ -214,7 +215,7 @@ void smf_5gc_n4_handle_session_modification_response(
ogs_error("No Cause");
smf_sbi_send_sm_context_update_error(session,
OGS_SBI_HTTP_STATUS_BAD_REQUEST,
"[PFCP] No Cause", NULL, NULL);
"[PFCP] No Cause", NULL, NULL, NULL);
return;
}
@ -228,6 +229,8 @@ void smf_5gc_n4_handle_session_deletion_response(
smf_sess_t *sess, ogs_pfcp_xact_t *xact,
ogs_pfcp_session_deletion_response_t *rsp)
{
int trigger;
ogs_sbi_session_t *session = NULL;
ogs_sbi_message_t sendmsg;
@ -238,6 +241,9 @@ void smf_5gc_n4_handle_session_deletion_response(
ogs_assert(session);
ogs_assert(rsp);
trigger = xact->trigger;
ogs_assert(trigger);
ogs_pfcp_xact_commit(xact);
if (rsp->cause.presence) {
@ -258,14 +264,20 @@ void smf_5gc_n4_handle_session_deletion_response(
return;
}
memset(&sendmsg, 0, sizeof(sendmsg));
if (trigger == OGS_PFCP_5GC_DELETE_TRIGGER_UE_REQUESTED) {
response = ogs_sbi_build_response(
&sendmsg, OGS_SBI_HTTP_STATUS_NO_CONTENT);
ogs_assert(response);
ogs_sbi_server_send_response(session, response);
smf_sbi_send_sm_context_updated_data_in_session_deletion(sess);
SMF_SESS_CLEAR(sess);
} else {
memset(&sendmsg, 0, sizeof(sendmsg));
response = ogs_sbi_build_response(
&sendmsg, OGS_SBI_HTTP_STATUS_NO_CONTENT);
ogs_assert(response);
ogs_sbi_server_send_response(session, response);
SMF_SESS_CLEAR(sess);
}
}
void smf_epc_n4_handle_session_establishment_response(

View File

@ -113,3 +113,34 @@ ogs_sbi_request_t *smf_namf_comm_build_n1_n2_message_transfer(
return request;
}
ogs_sbi_request_t *smf_namf_callback_build_sm_context_status(
smf_sess_t *sess, void *data)
{
ogs_sbi_message_t message;
ogs_sbi_request_t *request = NULL;
OpenAPI_sm_context_status_notification_t SmContextStatusNotification;
OpenAPI_status_info_t StatusInfo;
ogs_assert(sess);
ogs_assert(sess->sm_context_status_uri);
memset(&StatusInfo, 0, sizeof(StatusInfo));
StatusInfo.resource_status = OpenAPI_resource_status_RELEASED;
memset(&SmContextStatusNotification, 0,
sizeof(SmContextStatusNotification));
SmContextStatusNotification.status_info = &StatusInfo;
memset(&message, 0, sizeof(message));
message.h.method = (char *)OGS_SBI_HTTP_METHOD_POST;
message.h.uri = sess->sm_context_status_uri;
message.SmContextStatusNotification = &SmContextStatusNotification;
request = ogs_sbi_build_request(&message);
ogs_assert(request);
return request;
}

View File

@ -28,6 +28,9 @@ extern "C" {
ogs_sbi_request_t *smf_namf_comm_build_n1_n2_message_transfer(
smf_sess_t *sess, void *data);
ogs_sbi_request_t *smf_namf_callback_build_sm_context_status(
smf_sess_t *sess, void *data);
#ifdef __cplusplus
}

View File

@ -157,3 +157,23 @@ ogs_pkbuf_t *ngap_build_pdu_session_resource_setup_request_transfer(
return ogs_asn_encode(
&asn_DEF_NGAP_PDUSessionResourceSetupRequestTransfer, &message);
}
ogs_pkbuf_t *ngap_build_pdu_session_resource_release_command_transfer(
NGAP_Cause_PR group, long cause)
{
NGAP_PDUSessionResourceReleaseCommandTransfer_t message;
NGAP_Cause_t *Cause = NULL;
ogs_debug("PDUSessionResourceReleaseCommandTransfer");
memset(&message, 0,
sizeof(NGAP_PDUSessionResourceReleaseCommandTransfer_t));
ogs_debug(" Group[%d] Cause[%d]", group, (int)cause);
Cause = &message.cause;
Cause->present = group;
Cause->choice.radioNetwork = cause;
return ogs_asn_encode(
&asn_DEF_NGAP_PDUSessionResourceReleaseCommandTransfer, &message);
}

View File

@ -28,6 +28,8 @@ extern "C" {
ogs_pkbuf_t *ngap_build_pdu_session_resource_setup_request_transfer(
smf_sess_t *sess);
ogs_pkbuf_t *ngap_build_pdu_session_resource_release_command_transfer(
NGAP_Cause_PR group, long cause);
#ifdef __cplusplus
}

View File

@ -61,7 +61,7 @@ int ngap_handle_pdu_session_resource_setup_response_transfer(
smf_ue->supi, sess->psi);
smf_sbi_send_sm_context_update_error(session,
OGS_SBI_HTTP_STATUS_BAD_REQUEST,
"No N2 SM Info Type", smf_ue->supi, NULL);
"No N2 SM Info Type", smf_ue->supi, NULL, NULL);
goto cleanup;
}
@ -80,7 +80,7 @@ int ngap_handle_pdu_session_resource_setup_response_transfer(
smf_sbi_send_sm_context_update_error(session,
OGS_SBI_HTTP_STATUS_BAD_REQUEST,
"Unknown NGAP_UPTransportLayerInformation.present",
smf_ue->supi, NULL);
smf_ue->supi, NULL, NULL);
goto cleanup;
}
@ -99,7 +99,7 @@ int ngap_handle_pdu_session_resource_setup_response_transfer(
ogs_error("[%s:%d] No GTPTunnel", smf_ue->supi, sess->psi);
smf_sbi_send_sm_context_update_error(session,
OGS_SBI_HTTP_STATUS_BAD_REQUEST,
"No GTPTunnel", smf_ue->supi, NULL);
"No GTPTunnel", smf_ue->supi, NULL, NULL);
goto cleanup;
}

View File

@ -29,13 +29,16 @@ bool smf_nsmf_handle_create_sm_context(
smf_ue_t *smf_ue = NULL;
ogs_sbi_session_t *session = NULL;
ogs_pkbuf_t *n1smbuf = NULL;
ogs_sbi_client_t *client = NULL;
ogs_sockaddr_t *addr = NULL;
OpenAPI_sm_context_create_data_t *SmContextCreateData = NULL;
OpenAPI_snssai_t *sNssai = NULL;
OpenAPI_plmn_id_nid_t *servingNetwork = NULL;
OpenAPI_ref_to_binary_data_t *n1SmMsg = NULL;
ogs_pkbuf_t *n1smbuf = NULL;
ogs_assert(sess);
session = sess->sbi.session;
ogs_assert(session);
@ -102,6 +105,30 @@ bool smf_nsmf_handle_create_sm_context(
return false;
}
if (!SmContextCreateData->sm_context_status_uri) {
ogs_error("[%s:%d] No SmContextStatusNotification",
smf_ue->supi, sess->psi);
n1smbuf = gsm_build_pdu_session_establishment_reject(sess,
OGS_5GSM_CAUSE_INVALID_MANDATORY_INFORMATION);
smf_sbi_send_sm_context_create_error(session,
OGS_SBI_HTTP_STATUS_BAD_REQUEST,
"No SmContextStatusNotification", smf_ue->supi, n1smbuf);
return false;
}
addr = ogs_sbi_getaddr_from_uri(SmContextCreateData->sm_context_status_uri);
if (!addr) {
ogs_error("[%s:%d] Invalid URI [%s]",
smf_ue->supi, sess->psi,
SmContextCreateData->sm_context_status_uri);
n1smbuf = gsm_build_pdu_session_establishment_reject(sess,
OGS_5GSM_CAUSE_INVALID_MANDATORY_INFORMATION);
smf_sbi_send_sm_context_create_error(session,
OGS_SBI_HTTP_STATUS_BAD_REQUEST, "Invalid URI",
SmContextCreateData->sm_context_status_uri, n1smbuf);
return false;
}
ogs_plmn_id_build(&sess->plmn_id,
atoi(servingNetwork->mcc), atoi(servingNetwork->mnc),
strlen(servingNetwork->mnc));
@ -110,6 +137,20 @@ bool smf_nsmf_handle_create_sm_context(
sess->s_nssai.sst = sNssai->sst;
sess->s_nssai.sd = ogs_s_nssai_sd_from_string(sNssai->sd);
if (sess->sm_context_status_uri)
ogs_free(sess->sm_context_status_uri);
sess->sm_context_status_uri =
ogs_strdup(SmContextCreateData->sm_context_status_uri);
client = ogs_sbi_client_find(addr);
if (!client) {
client = ogs_sbi_client_add(addr);
ogs_assert(client);
}
OGS_SETUP_SBI_CLIENT(&sess->namf, client);
ogs_freeaddrinfo(addr);
if (SmContextCreateData->dnn) {
if (sess->dnn) ogs_free(sess->dnn);
sess->dnn = ogs_strdup(SmContextCreateData->dnn);
@ -140,8 +181,10 @@ bool smf_nsmf_handle_update_sm_context(
OpenAPI_sm_context_update_data_t *SmContextUpdateData = NULL;
OpenAPI_sm_context_updated_data_t SmContextUpdatedData;
OpenAPI_ref_to_binary_data_t *n1SmMsg = NULL;
OpenAPI_ref_to_binary_data_t *n2SmMsg = NULL;
ogs_pkbuf_t *n1smbuf = NULL;
ogs_pkbuf_t *n2smbuf = NULL;
ogs_assert(sess);
@ -158,11 +201,46 @@ bool smf_nsmf_handle_update_sm_context(
smf_ue->supi, sess->psi);
smf_sbi_send_sm_context_update_error(session,
OGS_SBI_HTTP_STATUS_BAD_REQUEST,
"No SmContextUpdateData", smf_ue->supi, NULL);
"No SmContextUpdateData", smf_ue->supi, NULL, NULL);
return false;
}
if (SmContextUpdateData->n1_sm_msg) {
n1SmMsg = SmContextUpdateData->n1_sm_msg;
if (!n1SmMsg || !n1SmMsg->content_id) {
ogs_error("[%s:%d] No n1SmMsg", smf_ue->supi, sess->psi);
n1smbuf = gsm_build_pdu_session_release_reject(sess,
OGS_5GSM_CAUSE_INVALID_MANDATORY_INFORMATION);
smf_sbi_send_sm_context_update_error(session,
OGS_SBI_HTTP_STATUS_BAD_REQUEST,
"No n1SmMsg", smf_ue->supi, n1smbuf, NULL);
return false;
}
n1smbuf = ogs_sbi_find_part_by_content_id(message, n1SmMsg->content_id);
if (!n1smbuf) {
ogs_error("[%s:%d] No N1 SM Content [%s]",
smf_ue->supi, sess->psi, n1SmMsg->content_id);
n1smbuf = gsm_build_pdu_session_release_reject(sess,
OGS_5GSM_CAUSE_INVALID_MANDATORY_INFORMATION);
smf_sbi_send_sm_context_update_error(session,
OGS_SBI_HTTP_STATUS_BAD_REQUEST,
"No N1 SM Content", smf_ue->supi, n1smbuf, NULL);
return false;
}
/*
* NOTE : The pkbuf created in the SBI message will be removed
* from ogs_sbi_message_free().
* So it must be copied and push a event queue.
*/
n1smbuf = ogs_pkbuf_copy(n1smbuf);
ogs_assert(n1smbuf);
nas_5gs_send_to_gsm(sess, n1smbuf);
return true;
if (SmContextUpdateData->n2_sm_info) {
} else if (SmContextUpdateData->n2_sm_info) {
/*********************************************************
* Handle ACTIVATED
@ -172,7 +250,7 @@ bool smf_nsmf_handle_update_sm_context(
ogs_error("[%s:%d] No n2SmInfoType", smf_ue->supi, sess->psi);
smf_sbi_send_sm_context_update_error(session,
OGS_SBI_HTTP_STATUS_BAD_REQUEST,
"No n2SmInfoType", smf_ue->supi, NULL);
"No n2SmInfoType", smf_ue->supi, NULL, NULL);
return false;
}
@ -182,7 +260,7 @@ bool smf_nsmf_handle_update_sm_context(
smf_ue->supi, sess->psi);
smf_sbi_send_sm_context_update_error(session,
OGS_SBI_HTTP_STATUS_BAD_REQUEST,
"No n2SmInfo.content_id", smf_ue->supi, NULL);
"No n2SmInfo.content_id", smf_ue->supi, NULL, NULL);
return false;
}
@ -191,7 +269,7 @@ bool smf_nsmf_handle_update_sm_context(
ogs_error("[%s:%d] No N2 SM Content", smf_ue->supi, sess->psi);
smf_sbi_send_sm_context_update_error(session,
OGS_SBI_HTTP_STATUS_BAD_REQUEST,
"No N2 SM Content", smf_ue->supi, NULL);
"No N2 SM Content", smf_ue->supi, NULL, NULL);
return false;
}
@ -212,7 +290,7 @@ bool smf_nsmf_handle_update_sm_context(
ogs_error("[%s:%d] No upCnxState", smf_ue->supi, sess->psi);
smf_sbi_send_sm_context_update_error(session,
OGS_SBI_HTTP_STATUS_BAD_REQUEST,
"No upCnxState", smf_ue->supi, NULL);
"No upCnxState", smf_ue->supi, NULL, NULL);
return false;
}
@ -254,7 +332,8 @@ bool smf_nsmf_handle_update_sm_context(
sess->ueUpCnxState, sess->smfUpCnxState);
ogs_error("%s", strerror);
smf_sbi_send_sm_context_update_error(session,
OGS_SBI_HTTP_STATUS_BAD_REQUEST, strerror, NULL, NULL);
OGS_SBI_HTTP_STATUS_BAD_REQUEST, strerror,
NULL, NULL, NULL);
ogs_free(strerror);
return false;
}
@ -352,7 +431,8 @@ bool smf_nsmf_handle_update_sm_context(
sess->ueUpCnxState, sess->smfUpCnxState);
ogs_error("%s", strerror);
smf_sbi_send_sm_context_update_error(session,
OGS_SBI_HTTP_STATUS_BAD_REQUEST, strerror, NULL, NULL);
OGS_SBI_HTTP_STATUS_BAD_REQUEST, strerror,
NULL, NULL, NULL);
ogs_free(strerror);
return false;
}
@ -366,7 +446,8 @@ bool smf_nsmf_handle_release_sm_context(
{
ogs_assert(sess);
smf_5gc_pfcp_send_session_deletion_request(sess);
smf_5gc_pfcp_send_session_deletion_request(
sess, OGS_PFCP_5GC_DELETE_TRIGGER_AMF_RELEASE_SM_CONTEXT);
return true;
}

View File

@ -300,9 +300,30 @@ void smf_5gc_pfcp_send_session_modification_request(smf_sess_t *sess)
ogs_expect(rv == OGS_OK);
}
void smf_5gc_pfcp_send_session_deletion_request(smf_sess_t *sess)
void smf_5gc_pfcp_send_session_deletion_request(smf_sess_t *sess, int trigger)
{
smf_epc_pfcp_send_session_deletion_request(sess, NULL);
int rv;
ogs_pkbuf_t *n4buf = NULL;
ogs_pfcp_header_t h;
ogs_pfcp_xact_t *xact = NULL;
ogs_assert(sess);
ogs_assert(trigger);
memset(&h, 0, sizeof(ogs_pfcp_header_t));
h.type = OGS_PFCP_SESSION_DELETION_REQUEST_TYPE;
h.seid = sess->upf_n4_seid;
n4buf = smf_n4_build_session_deletion_request(h.type, sess);
ogs_expect_or_return(n4buf);
xact = ogs_pfcp_xact_local_create(
sess->pfcp_node, &h, n4buf, timeout, sess);
ogs_expect_or_return(xact);
xact->trigger = trigger;
rv = ogs_pfcp_xact_commit(xact);
ogs_expect(rv == OGS_OK);
}
void smf_epc_pfcp_send_session_establishment_request(

View File

@ -36,7 +36,7 @@ void smf_pfcp_send_heartbeat_request(ogs_pfcp_node_t *node);
void smf_5gc_pfcp_send_session_establishment_request(smf_sess_t *sess);
void smf_5gc_pfcp_send_session_modification_request(smf_sess_t *sess);
void smf_5gc_pfcp_send_session_deletion_request(smf_sess_t *sess);
void smf_5gc_pfcp_send_session_deletion_request(smf_sess_t *sess, int trigger);
void smf_epc_pfcp_send_session_establishment_request(
smf_sess_t *sess, void *gtp_xact);

View File

@ -18,6 +18,7 @@
*/
#include "context.h"
#include "ngap-path.h"
#include "sbi-path.h"
static int server_cb(ogs_sbi_server_t *server,
@ -148,6 +149,24 @@ void smf_sbi_discover_and_send(
}
}
void smf_sbi_send_response(smf_sess_t *sess, int status)
{
ogs_sbi_session_t *session = NULL;
ogs_sbi_message_t sendmsg;
ogs_sbi_response_t *response = NULL;
ogs_assert(sess);
session = sess->sbi.session;
ogs_assert(session);
memset(&sendmsg, 0, sizeof(sendmsg));
response = ogs_sbi_build_response(&sendmsg, status);
ogs_assert(response);
ogs_sbi_server_send_response(session, response);
}
void smf_sbi_send_sm_context_create_error(
ogs_sbi_session_t *session,
int status, const char *title, const char *detail,
@ -158,7 +177,7 @@ void smf_sbi_send_sm_context_create_error(
OpenAPI_sm_context_create_error_t SmContextCreateError;
OpenAPI_problem_details_t problem;
OpenAPI_ref_to_binary_data_t n1_sm_msg;
OpenAPI_ref_to_binary_data_t n1SmMsg;
ogs_assert(session);
@ -174,8 +193,8 @@ void smf_sbi_send_sm_context_create_error(
SmContextCreateError.error = &problem;
if (n1smbuf) {
SmContextCreateError.n1_sm_msg = &n1_sm_msg;
n1_sm_msg.content_id = (char *)OGS_SBI_CONTENT_5GNAS_SM_ID;
SmContextCreateError.n1_sm_msg = &n1SmMsg;
n1SmMsg.content_id = (char *)OGS_SBI_CONTENT_5GNAS_SM_ID;
sendmsg.part[0].content_id = (char *)OGS_SBI_CONTENT_5GNAS_SM_ID;
sendmsg.part[0].content_type = (char *)OGS_SBI_CONTENT_5GNAS_TYPE;
sendmsg.part[0].pkbuf = n1smbuf;
@ -223,17 +242,82 @@ void smf_sbi_send_sm_context_updated_data(smf_sess_t *sess)
ogs_sbi_server_send_response(session, response);
}
void smf_sbi_send_sm_context_updated_data_in_session_deletion(smf_sess_t *sess)
{
int i;
ogs_sbi_session_t *session = NULL;
ogs_sbi_message_t sendmsg;
ogs_sbi_response_t *response = NULL;
OpenAPI_sm_context_updated_data_t SmContextUpdatedData;
OpenAPI_ref_to_binary_data_t n1SmMsg;
OpenAPI_ref_to_binary_data_t n2SmInfo;
ogs_assert(sess);
session = sess->sbi.session;
ogs_assert(session);
memset(&sendmsg, 0, sizeof(sendmsg));
memset(&SmContextUpdatedData, 0, sizeof(SmContextUpdatedData));
sendmsg.num_of_part = 0;
n1SmMsg.content_id = (char *)OGS_SBI_CONTENT_5GNAS_SM_ID;
SmContextUpdatedData.n1_sm_msg = &n1SmMsg;
sendmsg.part[sendmsg.num_of_part].pkbuf =
gsm_build_pdu_session_release_command(
sess, OGS_5GSM_CAUSE_REGULAR_DEACTIVATION);
if (sendmsg.part[sendmsg.num_of_part].pkbuf) {
sendmsg.part[sendmsg.num_of_part].content_id =
(char *)OGS_SBI_CONTENT_5GNAS_SM_ID;
sendmsg.part[sendmsg.num_of_part].content_type =
(char *)OGS_SBI_CONTENT_5GNAS_TYPE;
sendmsg.num_of_part++;
}
SmContextUpdatedData.n2_sm_info_type =
OpenAPI_n2_sm_info_type_PDU_RES_REL_CMD;
SmContextUpdatedData.n2_sm_info = &n2SmInfo;
memset(&n2SmInfo, 0, sizeof(n2SmInfo));
n2SmInfo.content_id = (char *)OGS_SBI_CONTENT_NGAP_SM_ID;
sendmsg.part[sendmsg.num_of_part].pkbuf =
ngap_build_pdu_session_resource_release_command_transfer(
NGAP_Cause_PR_nas, NGAP_CauseNas_normal_release);
if (sendmsg.part[sendmsg.num_of_part].pkbuf) {
sendmsg.part[sendmsg.num_of_part].content_id =
(char *)OGS_SBI_CONTENT_NGAP_SM_ID;
sendmsg.part[sendmsg.num_of_part].content_type =
(char *)OGS_SBI_CONTENT_NGAP_TYPE;
sendmsg.num_of_part++;
}
sendmsg.SmContextUpdatedData = &SmContextUpdatedData;
response = ogs_sbi_build_response(&sendmsg, OGS_SBI_HTTP_STATUS_OK);
ogs_assert(response);
ogs_sbi_server_send_response(session, response);
for (i = 0; i < sendmsg.num_of_part; i++)
ogs_pkbuf_free(sendmsg.part[i].pkbuf);
}
void smf_sbi_send_sm_context_update_error(
ogs_sbi_session_t *session,
int status, const char *title, const char *detail,
ogs_pkbuf_t *n2smbuf)
ogs_pkbuf_t *n1smbuf, ogs_pkbuf_t *n2smbuf)
{
ogs_sbi_message_t sendmsg;
ogs_sbi_response_t *response = NULL;
OpenAPI_sm_context_update_error_t SmContextUpdateError;
OpenAPI_problem_details_t problem;
OpenAPI_ref_to_binary_data_t n2_sm_info;
OpenAPI_ref_to_binary_data_t n1SmMsg;
OpenAPI_ref_to_binary_data_t n2SmInfo;
ogs_assert(session);
@ -248,13 +332,26 @@ void smf_sbi_send_sm_context_update_error(
memset(&SmContextUpdateError, 0, sizeof(SmContextUpdateError));
SmContextUpdateError.error = &problem;
if (n1smbuf) {
SmContextUpdateError.n1_sm_msg = &n1SmMsg;
n1SmMsg.content_id = (char *)OGS_SBI_CONTENT_5GNAS_SM_ID;
sendmsg.part[sendmsg.num_of_part].content_id =
(char *)OGS_SBI_CONTENT_5GNAS_SM_ID;
sendmsg.part[sendmsg.num_of_part].content_type =
(char *)OGS_SBI_CONTENT_5GNAS_TYPE;
sendmsg.part[sendmsg.num_of_part].pkbuf = n1smbuf;
sendmsg.num_of_part++;
}
if (n2smbuf) {
SmContextUpdateError.n2_sm_info = &n2_sm_info;
n2_sm_info.content_id = (char *)OGS_SBI_CONTENT_NGAP_SM_ID;
sendmsg.part[0].content_id = (char *)OGS_SBI_CONTENT_NGAP_SM_ID;
sendmsg.part[0].content_type = (char *)OGS_SBI_CONTENT_NGAP_TYPE;
sendmsg.part[0].pkbuf = n2smbuf;
sendmsg.num_of_part = 1;
SmContextUpdateError.n2_sm_info = &n2SmInfo;
n2SmInfo.content_id = (char *)OGS_SBI_CONTENT_NGAP_SM_ID;
sendmsg.part[sendmsg.num_of_part].content_id =
(char *)OGS_SBI_CONTENT_NGAP_SM_ID;
sendmsg.part[sendmsg.num_of_part].content_type =
(char *)OGS_SBI_CONTENT_NGAP_TYPE;
sendmsg.part[sendmsg.num_of_part].pkbuf = n2smbuf;
sendmsg.num_of_part++;
}
response = ogs_sbi_build_response(&sendmsg, problem.status);
@ -262,6 +359,52 @@ void smf_sbi_send_sm_context_update_error(
ogs_sbi_server_send_response(session, response);
if (n1smbuf)
ogs_pkbuf_free(n1smbuf);
if (n2smbuf)
ogs_pkbuf_free(n2smbuf);
}
#if 0
static int client_notify_cb(ogs_sbi_response_t *response, void *data)
{
int rv;
ogs_sbi_message_t message;
ogs_assert(response);
rv = ogs_sbi_parse_response(&message, response);
if (rv != OGS_OK) {
ogs_error("cannot parse HTTP response");
ogs_sbi_message_free(&message);
ogs_sbi_response_free(response);
return OGS_ERROR;
}
if (message.res_status != OGS_SBI_HTTP_STATUS_NO_CONTENT)
ogs_error("SmContextStatusNotification failed [%d]",
message.res_status);
ogs_sbi_message_free(&message);
ogs_sbi_response_free(response);
return OGS_OK;
}
#endif
void smf_sbi_send_sm_context_status_notify(smf_sess_t *sess)
{
ogs_sbi_request_t *request = NULL;
ogs_sbi_client_t *client = NULL;
ogs_assert(sess);
client = sess->namf.client;
ogs_assert(client);
client->cb = client_cb;
request = smf_namf_callback_build_sm_context_status(sess, NULL);
ogs_assert(request);
ogs_sbi_client_send_request(client, request, NULL);
ogs_sbi_request_free(request);
}

View File

@ -38,15 +38,20 @@ void smf_sbi_discover_and_send(
OpenAPI_nf_type_e nf_type, smf_sess_t *sess, void *data,
ogs_sbi_request_t *(*build)(smf_sess_t *sess, void *data));
void smf_sbi_send_response(smf_sess_t *sess, int status);
void smf_sbi_send_sm_context_create_error(
ogs_sbi_session_t *session,
int status, const char *title, const char *detail,
ogs_pkbuf_t *n1smbuf);
void smf_sbi_send_sm_context_updated_data(smf_sess_t *sess);
void smf_sbi_send_sm_context_updated_data_in_session_deletion(smf_sess_t *sess);
void smf_sbi_send_sm_context_update_error(
ogs_sbi_session_t *session,
int status, const char *title, const char *detail,
ogs_pkbuf_t *n2smbuf);
ogs_pkbuf_t *n1smbuf, ogs_pkbuf_t *n2smbuf);
void smf_sbi_send_sm_context_status_notify(smf_sess_t *sess);
#ifdef __cplusplus
}

View File

@ -332,7 +332,8 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e)
smf_sbi_send_sm_context_update_error(session,
OGS_SBI_HTTP_STATUS_BAD_REQUEST,
"No smContextRef",
sbi_message.h.resource.component[2], NULL);
sbi_message.h.resource.component[2],
NULL, NULL);
break;
}
@ -340,10 +341,12 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e)
sbi_message.h.resource.component[1]);
if (!sess) {
ogs_error("Not found [%s]", sbi_message.h.method);
ogs_error("Not found [%s]",
sbi_message.h.resource.component[1]);
smf_sbi_send_sm_context_update_error(session,
OGS_SBI_HTTP_STATUS_NOT_FOUND,
"Not found", sbi_message.h.method, NULL);
OGS_SBI_HTTP_STATUS_NOT_FOUND, "Not found",
sbi_message.h.resource.component[1],
NULL, NULL);
}
break;
@ -537,8 +540,6 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e)
break;
DEFAULT
ogs_error("Invalid API name [%s]", sbi_message.h.service.name);
ogs_assert_if_reached();
END
ogs_sbi_message_free(&sbi_message);
@ -612,7 +613,10 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e)
e->nas.message = &nas_message;
ogs_fsm_dispatch(&sess->sm, e);
if (OGS_FSM_CHECK(&sess->sm, smf_gsm_state_exception)) {
if (OGS_FSM_CHECK(&sess->sm, smf_gsm_state_released)) {
SMF_SESS_CLEAR(sess);
} else if (OGS_FSM_CHECK(&sess->sm, smf_gsm_state_exception)) {
ogs_error("State machine exception");
SMF_SESS_CLEAR(sess);
}

View File

@ -44,6 +44,7 @@ void smf_nf_state_exception(ogs_fsm_t *s, smf_event_t *e);
void smf_gsm_state_initial(ogs_fsm_t *s, smf_event_t *e);
void smf_gsm_state_final(ogs_fsm_t *s, smf_event_t *e);
void smf_gsm_state_operational(ogs_fsm_t *s, smf_event_t *e);
void smf_gsm_state_released(ogs_fsm_t *s, smf_event_t *e);
void smf_gsm_state_exception(ogs_fsm_t *s, smf_event_t *e);
void smf_pfcp_state_initial(ogs_fsm_t *s, smf_event_t *e);

View File

@ -88,3 +88,51 @@ ogs_pkbuf_t *testgsm_build_pdu_session_establishment_request(
return ogs_nas_5gs_plain_encode(&message);
}
ogs_pkbuf_t *testgsm_build_pdu_session_release_request(test_sess_t *test_sess)
{
ogs_nas_5gs_message_t message;
ogs_nas_5gs_pdu_session_release_request_t *pdu_session_release_request =
&message.gsm.pdu_session_release_request;
test_ue_t *test_ue = NULL;
ogs_pkbuf_t *pkbuf = NULL;
ogs_assert(test_sess);
test_ue = test_sess;
ogs_assert(test_ue);
memset(&message, 0, sizeof(message));
message.gsm.h.extended_protocol_discriminator =
OGS_NAS_EXTENDED_PROTOCOL_DISCRIMINATOR_5GSM;
message.gsm.h.pdu_session_identity = test_sess->psi;
message.gsm.h.procedure_transaction_identity = test_sess->pti;
message.gsm.h.message_type = OGS_NAS_5GS_PDU_SESSION_RELEASE_REQUEST;
return ogs_nas_5gs_plain_encode(&message);
}
ogs_pkbuf_t *testgsm_build_pdu_session_release_complete(test_sess_t *test_sess)
{
ogs_nas_5gs_message_t message;
ogs_nas_5gs_pdu_session_release_complete_t *pdu_session_release_complete =
&message.gsm.pdu_session_release_complete;
test_ue_t *test_ue = NULL;
ogs_pkbuf_t *pkbuf = NULL;
ogs_assert(test_sess);
test_ue = test_sess;
ogs_assert(test_ue);
memset(&message, 0, sizeof(message));
message.gsm.h.extended_protocol_discriminator =
OGS_NAS_EXTENDED_PROTOCOL_DISCRIMINATOR_5GSM;
message.gsm.h.pdu_session_identity = test_sess->psi;
message.gsm.h.procedure_transaction_identity = test_sess->pti;
message.gsm.h.message_type = OGS_NAS_5GS_PDU_SESSION_RELEASE_COMPLETE;
return ogs_nas_5gs_plain_encode(&message);
}

View File

@ -26,6 +26,8 @@ extern "C" {
ogs_pkbuf_t *testgsm_build_pdu_session_establishment_request(
test_sess_t *test_sess);
ogs_pkbuf_t *testgsm_build_pdu_session_release_request(test_sess_t *test_sess);
ogs_pkbuf_t *testgsm_build_pdu_session_release_complete(test_sess_t *test_sess);
#ifdef __cplusplus
}

View File

@ -84,6 +84,8 @@ void testgsm_recv(test_sess_t *sess, ogs_pkbuf_t *pkbuf)
testgsm_handle_pdu_session_establishment_accept(sess,
&message.gsm.pdu_session_establishment_accept);
break;
case OGS_NAS_5GS_PDU_SESSION_RELEASE_COMMAND:
break;
default:
ogs_error("Unknown message[%d]", message.gsm.h.message_type);
break;

View File

@ -19,7 +19,7 @@
#include "test-ngap.h"
static ogs_pkbuf_t *testngap_build_pdu_session_resource_response_trasfer(
static ogs_pkbuf_t *testngap_build_pdu_session_resource_setup_response_trasfer(
test_sess_t *sess);
ogs_pkbuf_t *testngap_build_ng_setup_request(uint32_t gnb_id, uint8_t bitsize)
@ -462,7 +462,8 @@ ogs_pkbuf_t *testngap_build_initial_context_setup_response(
PDUSessionItem->pDUSessionID = sess->psi;
n2smbuf = testngap_build_pdu_session_resource_response_trasfer(sess);
n2smbuf = testngap_build_pdu_session_resource_setup_response_trasfer(
sess);
ogs_assert(n2smbuf);
transfer = &PDUSessionItem->pDUSessionResourceSetupResponseTransfer;
@ -847,7 +848,7 @@ ogs_pkbuf_t *testngap_build_pdu_session_resource_setup_response(
PDUSessionItem->pDUSessionID = sess->psi;
n2smbuf = testngap_build_pdu_session_resource_response_trasfer(sess);
n2smbuf = testngap_build_pdu_session_resource_setup_response_trasfer(sess);
ogs_assert(n2smbuf);
transfer = &PDUSessionItem->pDUSessionResourceSetupResponseTransfer;
@ -859,7 +860,89 @@ ogs_pkbuf_t *testngap_build_pdu_session_resource_setup_response(
return nga_ngap_encode(&pdu);
}
static ogs_pkbuf_t *testngap_build_pdu_session_resource_response_trasfer(
ogs_pkbuf_t *testngap_build_pdu_session_resource_release_response(
test_sess_t *sess)
{
int rv;
test_ue_t *test_ue;
ogs_pkbuf_t *ngapbuf = NULL;
NGAP_NGAP_PDU_t pdu;
NGAP_SuccessfulOutcome_t *successfulOutcome = NULL;
NGAP_PDUSessionResourceReleaseResponse_t *PDUSessionResourceReleaseResponse;
NGAP_PDUSessionResourceReleaseResponseIEs_t *ie = NULL;
NGAP_AMF_UE_NGAP_ID_t *AMF_UE_NGAP_ID = NULL;
NGAP_RAN_UE_NGAP_ID_t *RAN_UE_NGAP_ID = NULL;
NGAP_PDUSessionResourceReleasedListRelRes_t *PDUSessionList = NULL;
NGAP_PDUSessionResourceReleasedItemRelRes_t *PDUSessionItem = NULL;
OCTET_STRING_t *transfer = NULL;
ogs_assert(sess);
test_ue = sess->test_ue;
ogs_assert(test_ue);
memset(&pdu, 0, sizeof (NGAP_NGAP_PDU_t));
pdu.present = NGAP_NGAP_PDU_PR_successfulOutcome;
pdu.choice.successfulOutcome = CALLOC(1, sizeof(NGAP_SuccessfulOutcome_t));
successfulOutcome = pdu.choice.successfulOutcome;
successfulOutcome->procedureCode =
NGAP_ProcedureCode_id_PDUSessionResourceRelease;
successfulOutcome->criticality = NGAP_Criticality_reject;
successfulOutcome->value.present =
NGAP_SuccessfulOutcome__value_PR_PDUSessionResourceReleaseResponse;
PDUSessionResourceReleaseResponse =
&successfulOutcome->value.choice.PDUSessionResourceReleaseResponse;
ie = CALLOC(1, sizeof(NGAP_PDUSessionResourceReleaseResponseIEs_t));
ASN_SEQUENCE_ADD(&PDUSessionResourceReleaseResponse->protocolIEs, ie);
ie->id = NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID;
ie->criticality = NGAP_Criticality_ignore;
ie->value.present =
NGAP_PDUSessionResourceReleaseResponseIEs__value_PR_AMF_UE_NGAP_ID;
AMF_UE_NGAP_ID = &ie->value.choice.AMF_UE_NGAP_ID;
ie = CALLOC(1, sizeof(NGAP_PDUSessionResourceReleaseResponseIEs_t));
ASN_SEQUENCE_ADD(&PDUSessionResourceReleaseResponse->protocolIEs, ie);
ie->id = NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID;
ie->criticality = NGAP_Criticality_ignore;
ie->value.present =
NGAP_PDUSessionResourceReleaseResponseIEs__value_PR_RAN_UE_NGAP_ID;
RAN_UE_NGAP_ID = &ie->value.choice.RAN_UE_NGAP_ID;
ie = CALLOC(1, sizeof(NGAP_PDUSessionResourceReleaseResponseIEs_t));
ASN_SEQUENCE_ADD(&PDUSessionResourceReleaseResponse->protocolIEs, ie);
ie->id = NGAP_ProtocolIE_ID_id_PDUSessionResourceReleasedListRelRes;
ie->criticality = NGAP_Criticality_ignore;
ie->value.present = NGAP_PDUSessionResourceReleaseResponseIEs__value_PR_PDUSessionResourceReleasedListRelRes;
PDUSessionList = &ie->value.choice.PDUSessionResourceReleasedListRelRes;
asn_uint642INTEGER(AMF_UE_NGAP_ID, test_ue->amf_ue_ngap_id);
*RAN_UE_NGAP_ID = test_ue->ran_ue_ngap_id;
PDUSessionItem =
CALLOC(1, sizeof(struct NGAP_PDUSessionResourceReleasedItemRelRes));
ASN_SEQUENCE_ADD(&PDUSessionList->list, PDUSessionItem);
PDUSessionItem->pDUSessionID = sess->psi;
transfer = &PDUSessionItem->pDUSessionResourceReleaseResponseTransfer;
transfer->size = 1;
transfer->buf = CALLOC(transfer->size, sizeof(uint8_t));
return nga_ngap_encode(&pdu);
}
static ogs_pkbuf_t *testngap_build_pdu_session_resource_setup_response_trasfer(
test_sess_t *sess)
{
ogs_ip_t gnb_n3_ip;

View File

@ -44,6 +44,8 @@ ogs_pkbuf_t *testngap_build_ue_context_release_complete(test_ue_t *test_ue);
ogs_pkbuf_t *testngap_build_pdu_session_resource_setup_response(
test_sess_t *sess);
ogs_pkbuf_t *testngap_build_pdu_session_resource_release_response(
test_sess_t *sess);
#ifdef __cplusplus
}

View File

@ -248,3 +248,44 @@ void testngap_handle_pdu_session_resource_setup_request(
}
}
}
void testngap_handle_pdu_session_resource_release_command(
test_ue_t *test_ue, ogs_ngap_message_t *message)
{
test_sess_t *sess = NULL;
int rv, i, j, k;
char buf[OGS_ADDRSTRLEN];
NGAP_NGAP_PDU_t pdu;
NGAP_InitiatingMessage_t *initiatingMessage = NULL;
NGAP_PDUSessionResourceReleaseCommand_t *PDUSessionResourceReleaseCommand;
NGAP_PDUSessionResourceReleaseCommandIEs_t *ie = NULL;
NGAP_NAS_PDU_t *NAS_PDU = NULL;
ogs_assert(test_ue);
sess = test_ue->sess;
ogs_assert(sess);
ogs_assert(message);
initiatingMessage = message->choice.initiatingMessage;
ogs_assert(initiatingMessage);
PDUSessionResourceReleaseCommand =
&initiatingMessage->value.choice.PDUSessionResourceReleaseCommand;
ogs_assert(PDUSessionResourceReleaseCommand);
for (i = 0; i < PDUSessionResourceReleaseCommand->protocolIEs.list.count;
i++) {
ie = PDUSessionResourceReleaseCommand->protocolIEs.list.array[i];
switch (ie->id) {
case NGAP_ProtocolIE_ID_id_NAS_PDU:
NAS_PDU = &ie->value.choice.NAS_PDU;
break;
default:
break;
}
}
if (NAS_PDU)
testngap_send_to_nas(test_ue, NAS_PDU);
}

View File

@ -33,6 +33,8 @@ void testngap_handle_initial_context_setup_request(
test_ue_t *test_ue, ogs_ngap_message_t *message);
void testngap_handle_pdu_session_resource_setup_request(
test_ue_t *test_ue, ogs_ngap_message_t *message);
void testngap_handle_pdu_session_resource_release_command(
test_ue_t *test_ue, ogs_ngap_message_t *message);
#ifdef __cplusplus
}

View File

@ -53,6 +53,9 @@ void testngap_recv(test_ue_t *test_ue, ogs_pkbuf_t *pkbuf)
case NGAP_ProcedureCode_id_PDUSessionResourceSetup:
testngap_handle_pdu_session_resource_setup_request(test_ue, pdu);
break;
case NGAP_ProcedureCode_id_PDUSessionResourceRelease:
testngap_handle_pdu_session_resource_release_command(test_ue, pdu);
break;
case NGAP_ProcedureCode_id_UEContextRelease:
/* Nothing */
break;

View File

@ -523,11 +523,362 @@ static void test1_func(abts_case *tc, void *data)
test_ue_remove(&test_ue);
}
static void test2_func(abts_case *tc, void *data)
{
int rv;
ogs_socknode_t *ngap;
ogs_socknode_t *gtpu;
ogs_pkbuf_t *gmmbuf;
ogs_pkbuf_t *gsmbuf;
ogs_pkbuf_t *nasbuf;
ogs_pkbuf_t *sendbuf;
ogs_pkbuf_t *recvbuf;
ogs_ngap_message_t message;
int i;
int msgindex = 0;
ogs_nas_5gs_mobile_identity_suci_t mobile_identity_suci;
test_ue_t test_ue;
test_sess_t test_sess;
uint8_t tmp[OGS_MAX_SDU_LEN];
const char *_k_string = "70d49a71dd1a2b806a25abe0ef749f1e";
uint8_t k[OGS_KEY_LEN];
const char *_opc_string = "6f1bf53d624b3a43af6592854e2444c7";
uint8_t opc[OGS_KEY_LEN];
mongoc_collection_t *collection = NULL;
bson_t *doc = NULL;
int64_t count = 0;
bson_error_t error;
const char *json =
"{"
"\"_id\" : { \"$oid\" : \"597223158b8861d7605378c6\" }, "
"\"imsi\" : \"901700000021309\","
"\"ambr\" : { "
"\"uplink\" : { \"$numberLong\" : \"1024000\" }, "
"\"downlink\" : { \"$numberLong\" : \"1024000\" } "
"},"
"\"pdn\" : ["
"{"
"\"apn\" : \"internet\", "
"\"_id\" : { \"$oid\" : \"597223158b8861d7605378c7\" }, "
"\"ambr\" : {"
"\"uplink\" : { \"$numberLong\" : \"1024000\" }, "
"\"downlink\" : { \"$numberLong\" : \"1024000\" } "
"},"
"\"qos\" : { "
"\"qci\" : 9, "
"\"arp\" : { "
"\"priority_level\" : 8,"
"\"pre_emption_vulnerability\" : 1, "
"\"pre_emption_capability\" : 1"
"} "
"}, "
"\"type\" : 2"
"}"
"],"
"\"security\" : { "
"\"k\" : \"70d49a71dd1a2b806a25abe0ef749f1e\", "
"\"opc\" : \"6f1bf53d624b3a43af6592854e2444c7\", "
"\"amf\" : \"8000\", "
"\"sqn\" : { \"$numberLong\" : \"25235952177090\" } "
"}, "
"\"subscribed_rau_tau_timer\" : 12,"
"\"network_access_mode\" : 2, "
"\"subscriber_status\" : 0, "
"\"access_restriction_data\" : 32, "
"\"__v\" : 0 "
"}";
/* Setup Test UE & Session Context */
memset(&test_ue, 0, sizeof(test_ue));
memset(&test_sess, 0, sizeof(test_sess));
test_sess.test_ue = &test_ue;
test_ue.sess = &test_sess;
test_ue.nas.registration.type = OGS_NAS_KSI_NO_KEY_IS_AVAILABLE;
test_ue.nas.registration.follow_on_request = 1;
test_ue.nas.registration.value = OGS_NAS_5GS_REGISTRATION_TYPE_INITIAL;
memset(&mobile_identity_suci, 0, sizeof(mobile_identity_suci));
mobile_identity_suci.h.supi_format = OGS_NAS_5GS_SUPI_FORMAT_IMSI;
mobile_identity_suci.h.type = OGS_NAS_5GS_MOBILE_IDENTITY_SUCI;
ogs_nas_from_plmn_id(&mobile_identity_suci.nas_plmn_id,
&test_self()->tai.plmn_id);
mobile_identity_suci.routing_indicator1 = 0;
mobile_identity_suci.routing_indicator2 = 0xf;
mobile_identity_suci.routing_indicator3 = 0xf;
mobile_identity_suci.routing_indicator4 = 0xf;
mobile_identity_suci.protection_scheme_id = OGS_NAS_5GS_NULL_SCHEME;
mobile_identity_suci.home_network_pki_value = 0;
mobile_identity_suci.scheme_output[0] = 0;
mobile_identity_suci.scheme_output[1] = 0;
mobile_identity_suci.scheme_output[2] = 0x20;
mobile_identity_suci.scheme_output[3] = 0x31;
mobile_identity_suci.scheme_output[4] = 0x90;
test_ue_set_mobile_identity_suci(&test_ue, &mobile_identity_suci, 13);
memset(&test_ue.mobile_identity_imeisv, 0,
sizeof(ogs_nas_mobile_identity_imeisv_t));
test_ue.mobile_identity_imeisv.type = OGS_NAS_5GS_MOBILE_IDENTITY_IMEISV;
test_ue.mobile_identity_imeisv.odd_even = OGS_NAS_MOBILE_IDENTITY_EVEN;
test_ue.mobile_identity_imeisv.digit1 = 8;
test_ue.mobile_identity_imeisv.digit2 = 6;
test_ue.mobile_identity_imeisv.digit3 = 6;
test_ue.mobile_identity_imeisv.digit4 = 5;
test_ue.mobile_identity_imeisv.digit5 = 0;
test_ue.mobile_identity_imeisv.digit6 = 7;
test_ue.mobile_identity_imeisv.digit7 = 0;
test_ue.mobile_identity_imeisv.digit8 = 4;
test_ue.mobile_identity_imeisv.digit9 = 0;
test_ue.mobile_identity_imeisv.digit10 = 0;
test_ue.mobile_identity_imeisv.digit11 = 4;
test_ue.mobile_identity_imeisv.digit12 = 0;
test_ue.mobile_identity_imeisv.digit13 = 5;
test_ue.mobile_identity_imeisv.digit14 = 3;
test_ue.mobile_identity_imeisv.digit15 = 0;
test_ue.mobile_identity_imeisv.digit16 = 1;
test_ue.mobile_identity_imeisv.digit17 = 0xf;
test_ue.nas.access_type = OGS_ACCESS_TYPE_3GPP;
test_ue.abba_len = 2;
OGS_HEX(_k_string, strlen(_k_string), test_ue.k);
OGS_HEX(_opc_string, strlen(_opc_string), test_ue.opc);
test_sess.psi = 5;
test_sess.pti = 1;
test_sess.pdu_session_type = OGS_PDU_SESSION_TYPE_IPV4V6;
test_sess.dnn = (char *)"internet";
memset(&test_sess.gnb_n3_ip, 0, sizeof(test_sess.gnb_n3_ip));
test_sess.gnb_n3_ip.ipv4 = true;
test_sess.gnb_n3_ip.addr = inet_addr("127.0.0.5");
test_sess.gnb_n3_teid = 0;
/* gNB connects to AMF */
ngap = testgnb_ngap_client("127.0.0.2");
ABTS_PTR_NOTNULL(tc, ngap);
/* gNB connects to UPF */
gtpu = testgnb_gtpu_server("127.0.0.5");
ABTS_PTR_NOTNULL(tc, gtpu);
/* Send NG-Setup Reqeust */
sendbuf = testngap_build_ng_setup_request(0x4000, 22);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Receive NG-Setup Response */
recvbuf = testgnb_ngap_read(ngap);
ABTS_PTR_NOTNULL(tc, recvbuf);
testngap_recv(&test_ue, recvbuf);
/********** Insert Subscriber in Database */
collection = mongoc_client_get_collection(
ogs_mongoc()->client, ogs_mongoc()->name, "subscribers");
ABTS_PTR_NOTNULL(tc, collection);
doc = BCON_NEW("imsi", BCON_UTF8(test_ue.imsi));
ABTS_PTR_NOTNULL(tc, doc);
count = mongoc_collection_count (
collection, MONGOC_QUERY_NONE, doc, 0, 0, NULL, &error);
if (count) {
ABTS_TRUE(tc, mongoc_collection_remove(collection,
MONGOC_REMOVE_SINGLE_REMOVE, doc, NULL, &error))
}
bson_destroy(doc);
doc = bson_new_from_json((const uint8_t *)json, -1, &error);;
ABTS_PTR_NOTNULL(tc, doc);
ABTS_TRUE(tc, mongoc_collection_insert(collection,
MONGOC_INSERT_NONE, doc, NULL, &error));
bson_destroy(doc);
doc = BCON_NEW("imsi", BCON_UTF8(test_ue.imsi));
ABTS_PTR_NOTNULL(tc, doc);
do {
count = mongoc_collection_count (
collection, MONGOC_QUERY_NONE, doc, 0, 0, NULL, &error);
} while (count == 0);
bson_destroy(doc);
/* Send Registration request */
test_ue.registration_request_type.guti = 1;
gmmbuf = testgmm_build_registration_request(&test_ue, NULL);
ABTS_PTR_NOTNULL(tc, gmmbuf);
test_ue.registration_request_type.requested_nssai = 1;
test_ue.registration_request_type.last_visited_registered_tai = 1;
test_ue.registration_request_type.ue_usage_setting = 1;
nasbuf = testgmm_build_registration_request(&test_ue, NULL);
ABTS_PTR_NOTNULL(tc, nasbuf);
sendbuf = testngap_build_initial_ue_message(&test_ue, gmmbuf, false);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Receive Identity request */
recvbuf = testgnb_ngap_read(ngap);
ABTS_PTR_NOTNULL(tc, recvbuf);
testngap_recv(&test_ue, recvbuf);
/* Send Identity response */
gmmbuf = testgmm_build_identity_response(&test_ue);
ABTS_PTR_NOTNULL(tc, gmmbuf);
sendbuf = testngap_build_uplink_nas_transport(&test_ue, gmmbuf);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Receive Authentication request */
recvbuf = testgnb_ngap_read(ngap);
ABTS_PTR_NOTNULL(tc, recvbuf);
testngap_recv(&test_ue, recvbuf);
/* Send Authentication response */
gmmbuf = testgmm_build_authentication_response(&test_ue);
ABTS_PTR_NOTNULL(tc, gmmbuf);
sendbuf = testngap_build_uplink_nas_transport(&test_ue, gmmbuf);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Receive Security mode command */
recvbuf = testgnb_ngap_read(ngap);
ABTS_PTR_NOTNULL(tc, recvbuf);
testngap_recv(&test_ue, recvbuf);
/* Send Security mode complete */
gmmbuf = testgmm_build_security_mode_complete(&test_ue, nasbuf);
ABTS_PTR_NOTNULL(tc, gmmbuf);
sendbuf = testngap_build_uplink_nas_transport(&test_ue, gmmbuf);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Receive Initial context setup request */
recvbuf = testgnb_ngap_read(ngap);
ABTS_PTR_NOTNULL(tc, recvbuf);
testngap_recv(&test_ue, recvbuf);
/* Send UE radio capability info indication */
sendbuf = testngap_build_ue_radio_capability_info_indication(&test_ue);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Send Initial context setup response */
sendbuf = testngap_build_initial_context_setup_response(&test_ue, NULL);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Send Registration complete */
gmmbuf = testgmm_build_registration_complete(&test_ue);
ABTS_PTR_NOTNULL(tc, gmmbuf);
sendbuf = testngap_build_uplink_nas_transport(&test_ue, gmmbuf);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Receive Configuration update command */
recvbuf = testgnb_ngap_read(ngap);
ABTS_PTR_NOTNULL(tc, recvbuf);
testngap_recv(&test_ue, recvbuf);
/* Send PDU session establishment request */
gsmbuf = testgsm_build_pdu_session_establishment_request(&test_sess);
ABTS_PTR_NOTNULL(tc, gsmbuf);
gmmbuf = testgmm_build_ul_nas_transport(&test_sess,
OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf);
ABTS_PTR_NOTNULL(tc, gmmbuf);
sendbuf = testngap_build_uplink_nas_transport(&test_ue, gmmbuf);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Receive PDU session establishment accept */
recvbuf = testgnb_ngap_read(ngap);
ABTS_PTR_NOTNULL(tc, recvbuf);
testngap_recv(&test_ue, recvbuf);
/* Send PDU session resource setup response */
sendbuf = testngap_build_pdu_session_resource_setup_response(&test_sess);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
ogs_msleep(100);
/* Send PDU Session release request */
gsmbuf = testgsm_build_pdu_session_release_request(&test_sess);
ABTS_PTR_NOTNULL(tc, gsmbuf);
gmmbuf = testgmm_build_ul_nas_transport(&test_sess,
OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf);
ABTS_PTR_NOTNULL(tc, gmmbuf);
sendbuf = testngap_build_uplink_nas_transport(&test_ue, gmmbuf);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Receive PDU session release command */
recvbuf = testgnb_ngap_read(ngap);
ABTS_PTR_NOTNULL(tc, recvbuf);
testngap_recv(&test_ue, recvbuf);
/* Send PDU session resource release response */
sendbuf = testngap_build_pdu_session_resource_release_response(&test_sess);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
ogs_msleep(100);
/* Send PDU session resource release complete */
gsmbuf = testgsm_build_pdu_session_release_complete(&test_sess);
ABTS_PTR_NOTNULL(tc, gsmbuf);
gmmbuf = testgmm_build_ul_nas_transport(&test_sess,
OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf);
ABTS_PTR_NOTNULL(tc, gmmbuf);
sendbuf = testngap_build_uplink_nas_transport(&test_ue, gmmbuf);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
ogs_msleep(100);
/********** Remove Subscriber in Database */
doc = BCON_NEW("imsi", BCON_UTF8(test_ue.imsi));
ABTS_PTR_NOTNULL(tc, doc);
ABTS_TRUE(tc, mongoc_collection_remove(collection,
MONGOC_REMOVE_SINGLE_REMOVE, doc, NULL, &error))
bson_destroy(doc);
mongoc_collection_destroy(collection);
/* gNB disonncect from UPF */
testgnb_gtpu_close(gtpu);
/* gNB disonncect from AMF */
testgnb_ngap_close(ngap);
/* Clear Test UE Context */
test_ue_remove(&test_ue);
}
abts_suite *test_guti(abts_suite *suite)
{
suite = ADD_SUITE(suite)
abts_run_test(suite, test1_func, NULL);
abts_run_test(suite, test2_func, NULL);
return suite;
}