diff --git a/CMakeLists.txt b/CMakeLists.txt index 015e66e46d..f0b080f5c8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -435,6 +435,7 @@ add_library(ngap ${NGAP_DIR}/ngap_gNB_itti_messaging.c ${NGAP_DIR}/ngap_gNB_management_procedures.c ${NGAP_DIR}/ngap_gNB_nas_procedures.c + ${NGAP_DIR}/ngap_gNB_pdu_session_management.c ${NGAP_DIR}/ngap_gNB_nnsf.c ${NGAP_DIR}/ngap_gNB_overload.c ${NGAP_DIR}/ngap_gNB_trace.c diff --git a/openair3/NGAP/ngap_common.c b/openair3/NGAP/ngap_common.c index 8be57349ec..b5cb2c78be 100644 --- a/openair3/NGAP/ngap_common.c +++ b/openair3/NGAP/ngap_common.c @@ -271,3 +271,43 @@ bool decodePDUSessionResourceSetup(pdusession_transfer_t *out, const OCTET_STRIN return true; } + +/** @brief PDU Session Resource Setup Response Transfer encoding (9.3.4.2 3GPP TS 38.413) */ +byte_array_t encode_ngap_pdusession_setup_response_transfer(const pdusession_setup_t *pdusession) +{ + NGAP_PDUSessionResourceSetupResponseTransfer_t pdusessionTransfer = {0}; + byte_array_t out = {0}; + + // DL QoS Flow per TNL Information (Mandatory) + NGAP_QosFlowPerTNLInformation_t *dLQosFlowPerTNLInformation = &pdusessionTransfer.dLQosFlowPerTNLInformation; + + // UP Transport Layer Information (Mandatory) + dLQosFlowPerTNLInformation->uPTransportLayerInformation.present = NGAP_UPTransportLayerInformation_PR_gTPTunnel; + asn1cCalloc(dLQosFlowPerTNLInformation->uPTransportLayerInformation.choice.gTPTunnel, gtp); + GTP_TEID_TO_ASN1(pdusession->n3_outgoing.teid, >p->gTP_TEID); + tnl_to_bitstring(>p->transportLayerAddress, pdusession->n3_outgoing.addr); + char ip_str[INET_ADDRSTRLEN] = {0}; + inet_ntop(AF_INET, gtp->transportLayerAddress.buf, ip_str, sizeof(ip_str)); + NGAP_DEBUG("Encoded PDU Session Transfer (%d): TEID=0x%08x, Addr=%s\n", + pdusession->pdusession_id, + pdusession->n3_outgoing.teid, + ip_str); + + // Associated QoS Flow List (Mandatory) + for (int j = 0; j < pdusession->nb_of_qos_flow; j++) { + asn1cSequenceAdd(dLQosFlowPerTNLInformation->associatedQosFlowList.list, NGAP_AssociatedQosFlowItem_t, qos_item); + // QoS Flow Identifier (Mandatory) + qos_item->qosFlowIdentifier = pdusession->associated_qos_flows[j].qfi; + } + + // Encode + asn_encode_to_new_buffer_result_t res = asn_encode_to_new_buffer(NULL, + ATS_ALIGNED_CANONICAL_PER, + &asn_DEF_NGAP_PDUSessionResourceSetupResponseTransfer, + &pdusessionTransfer); + AssertFatal(res.buffer, "ASN1 message encoding failed (%s, %lu)!\n", res.result.failed_type->name, res.result.encoded); + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_PDUSessionResourceSetupResponseTransfer, &pdusessionTransfer); + out.buf = res.buffer; + out.len = res.result.encoded; + return out; +} diff --git a/openair3/NGAP/ngap_common.h b/openair3/NGAP/ngap_common.h index 986a7b59bf..fcd999ae33 100644 --- a/openair3/NGAP/ngap_common.h +++ b/openair3/NGAP/ngap_common.h @@ -91,7 +91,7 @@ void encode_ngap_nr_cgi(NGAP_NR_CGI_t *out, const plmn_id_t *plmn, const uint32_ pdusession_level_qos_parameter_t fill_qos(uint8_t qfi, const NGAP_QosFlowLevelQosParameters_t *params); void *decode_pdusession_transfer(const asn_TYPE_descriptor_t *td, const OCTET_STRING_t buf); bool decodePDUSessionResourceSetup(pdusession_transfer_t *out, const OCTET_STRING_t in); +byte_array_t encode_ngap_pdusession_setup_response_transfer(const pdusession_setup_t *pdusession); /** @}*/ - #endif /* NGAP_COMMON_H_ */ diff --git a/openair3/NGAP/ngap_gNB.c b/openair3/NGAP/ngap_gNB.c index b03e153486..257ca25f1a 100644 --- a/openair3/NGAP/ngap_gNB.c +++ b/openair3/NGAP/ngap_gNB.c @@ -57,6 +57,7 @@ #include "ngap_messages_types.h" #include "ngap_gNB_mobility_management.h" #include "ngap_gNB_ue_context.h" +#include "ngap_gNB_pdu_session_management.h" #include "oai_asn1.h" #include "openair3/SECU/kdf.h" #include "queue.h" diff --git a/openair3/NGAP/ngap_gNB_handlers.c b/openair3/NGAP/ngap_gNB_handlers.c index 292ab1635d..1e5b024190 100644 --- a/openair3/NGAP/ngap_gNB_handlers.c +++ b/openair3/NGAP/ngap_gNB_handlers.c @@ -47,6 +47,7 @@ #include "ngap_gNB_nnsf.h" #include "ngap_gNB_management_procedures.h" #include "ngap_gNB_mobility_management.h" +#include "ngap_gNB_pdu_session_management.h" #include "ngap_gNB_nas_procedures.h" #include "ngap_gNB_trace.h" #include "ngap_gNB_ue_context.h" diff --git a/openair3/NGAP/ngap_gNB_nas_procedures.c b/openair3/NGAP/ngap_gNB_nas_procedures.c index 8a2cfeead5..2d4bd3eefa 100644 --- a/openair3/NGAP/ngap_gNB_nas_procedures.c +++ b/openair3/NGAP/ngap_gNB_nas_procedures.c @@ -558,64 +558,6 @@ int ngap_gNB_nas_non_delivery_ind(instance_t instance, return 0; } -/** @brief PDU Session Resource Setup Response Transfer encoding (9.3.4.2 3GPP TS 38.413) */ -static byte_array_t encode_ngap_pdusession_setup_response_transfer(const pdusession_setup_t *pdusession) -{ - NGAP_PDUSessionResourceSetupResponseTransfer_t pdusessionTransfer = {0}; - byte_array_t out = {0}; - - // DL QoS Flow per TNL Information (Mandatory) - NGAP_QosFlowPerTNLInformation_t *dLQosFlowPerTNLInformation = &pdusessionTransfer.dLQosFlowPerTNLInformation; - - // UP Transport Layer Information (Mandatory) - dLQosFlowPerTNLInformation->uPTransportLayerInformation.present = NGAP_UPTransportLayerInformation_PR_gTPTunnel; - asn1cCalloc(dLQosFlowPerTNLInformation->uPTransportLayerInformation.choice.gTPTunnel, gtp); - GTP_TEID_TO_ASN1(pdusession->n3_outgoing.teid, >p->gTP_TEID); - tnl_to_bitstring(>p->transportLayerAddress, pdusession->n3_outgoing.addr); - char ip_str[INET_ADDRSTRLEN] = {0}; - inet_ntop(AF_INET, gtp->transportLayerAddress.buf, ip_str, sizeof(ip_str)); - NGAP_DEBUG("Encoded PDU Session Transfer (%d): TEID=0x%08x, Addr=%s\n", - pdusession->pdusession_id, - pdusession->n3_outgoing.teid, - ip_str); - - // Associated QoS Flow List (Mandatory) - for (int j = 0; j < pdusession->nb_of_qos_flow; j++) { - asn1cSequenceAdd(dLQosFlowPerTNLInformation->associatedQosFlowList.list, NGAP_AssociatedQosFlowItem_t, qos_item); - // QoS Flow Identifier (Mandatory) - qos_item->qosFlowIdentifier = pdusession->associated_qos_flows[j].qfi; - } - - // Encode - asn_encode_to_new_buffer_result_t res = asn_encode_to_new_buffer(NULL, - ATS_ALIGNED_CANONICAL_PER, - &asn_DEF_NGAP_PDUSessionResourceSetupResponseTransfer, - &pdusessionTransfer); - AssertFatal(res.buffer, "ASN1 message encoding failed (%s, %lu)!\n", res.result.failed_type->name, res.result.encoded); - ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_PDUSessionResourceSetupResponseTransfer, &pdusessionTransfer); - out.buf = res.buffer; - out.len = res.result.encoded; - return out; -} - -/** @brief PDU Session Resource Release Response Transfer encoding (9.3.4.21 3GPP TS 38.413) - * The transfer structure contains only an optional Secondary RAT Usage Information IE. - * Since we don't use secondary RAT (MR-DC), we encode an empty structure. */ -static byte_array_t encode_ngap_pdusession_release_response_transfer(void) -{ - NGAP_PDUSessionResourceReleaseResponseTransfer_t pdusessionTransfer = {0}; - - // Encode - asn_encode_to_new_buffer_result_t res = asn_encode_to_new_buffer(NULL, - ATS_ALIGNED_CANONICAL_PER, - &asn_DEF_NGAP_PDUSessionResourceReleaseResponseTransfer, - &pdusessionTransfer); - AssertFatal(res.buffer, "ASN1 message encoding failed (%s, %lu)!\n", res.result.failed_type->name, res.result.encoded); - ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_PDUSessionResourceReleaseResponseTransfer, &pdusessionTransfer); - byte_array_t out = {.buf = res.buffer, .len = res.result.encoded}; - return out; -} - //------------------------------------------------------------------------------ int ngap_gNB_initial_ctxt_resp(instance_t instance, ngap_initial_context_setup_resp_t *initial_ctxt_resp_p) //------------------------------------------------------------------------------ @@ -909,354 +851,3 @@ int ngap_gNB_ue_capabilities(instance_t instance, ngap_ue_cap_info_ind_t *ue_cap ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, &pdu); return 0; } - -//------------------------------------------------------------------------------ -int ngap_gNB_pdusession_setup_resp(instance_t instance, ngap_pdusession_setup_resp_t *pdusession_setup_resp_p) -//------------------------------------------------------------------------------ -{ - ngap_gNB_instance_t *ngap_gNB_instance_p = NULL; - struct ngap_gNB_ue_context_s *ue_context_p = NULL; - NGAP_NGAP_PDU_t pdu = {0}; - uint8_t *buffer = NULL; - uint32_t length; - - /* Retrieve the NGAP gNB instance associated with Mod_id */ - ngap_gNB_instance_p = ngap_gNB_get_instance(instance); - DevAssert(pdusession_setup_resp_p != NULL); - DevAssert(ngap_gNB_instance_p != NULL); - - if ((ue_context_p = ngap_get_ue_context(pdusession_setup_resp_p->gNB_ue_ngap_id)) == NULL) { - /* The context for this gNB ue ngap id doesn't exist in the map of gNB UEs */ - NGAP_WARN("Failed to find ue context associated with gNB ue ngap id: 0x%08x\n", pdusession_setup_resp_p->gNB_ue_ngap_id); - return -1; - } - - /* Uplink NAS transport can occur either during an ngap connected state - * or during initial attach (for example: NAS authentication). - */ - if (!(ue_context_p->ue_state == NGAP_UE_CONNECTED || ue_context_p->ue_state == NGAP_UE_WAITING_CSR)) { - NGAP_WARN( - "You are attempting to send NAS data over non-connected " - "gNB ue ngap id: %08x, current state: %d\n", - pdusession_setup_resp_p->gNB_ue_ngap_id, - ue_context_p->ue_state); - return -1; - } - - /* Prepare the NGAP message to encode */ - pdu.present = NGAP_NGAP_PDU_PR_successfulOutcome; - asn1cCalloc(pdu.choice.successfulOutcome, successfulOutcome); - successfulOutcome->procedureCode = NGAP_ProcedureCode_id_PDUSessionResourceSetup; - successfulOutcome->criticality = NGAP_Criticality_reject; - successfulOutcome->value.present = NGAP_SuccessfulOutcome__value_PR_PDUSessionResourceSetupResponse; - NGAP_PDUSessionResourceSetupResponse_t *out = &successfulOutcome->value.choice.PDUSessionResourceSetupResponse; - /* mandatory */ - { - asn1cSequenceAdd(out->protocolIEs.list, NGAP_PDUSessionResourceSetupResponseIEs_t, ie); - ie->id = NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID; - ie->criticality = NGAP_Criticality_ignore; - ie->value.present = NGAP_PDUSessionResourceSetupResponseIEs__value_PR_AMF_UE_NGAP_ID; - asn_uint642INTEGER(&ie->value.choice.AMF_UE_NGAP_ID, ue_context_p->amf_ue_ngap_id); - } - /* mandatory */ - { - asn1cSequenceAdd(out->protocolIEs.list, NGAP_PDUSessionResourceSetupResponseIEs_t, ie); - ie->id = NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID; - ie->criticality = NGAP_Criticality_ignore; - ie->value.present = NGAP_PDUSessionResourceSetupResponseIEs__value_PR_RAN_UE_NGAP_ID; - ie->value.choice.RAN_UE_NGAP_ID = pdusession_setup_resp_p->gNB_ue_ngap_id; - } - - /* optional */ - if (pdusession_setup_resp_p->nb_of_pdusessions > 0) { - asn1cSequenceAdd(out->protocolIEs.list, NGAP_PDUSessionResourceSetupResponseIEs_t, ie3); - ie3->id = NGAP_ProtocolIE_ID_id_PDUSessionResourceSetupListSURes; - ie3->criticality = NGAP_Criticality_ignore; - ie3->value.present = NGAP_PDUSessionResourceSetupResponseIEs__value_PR_PDUSessionResourceSetupListSURes; - - for (int i = 0; i < pdusession_setup_resp_p->nb_of_pdusessions; i++) { - pdusession_setup_t *pdusession = pdusession_setup_resp_p->pdusessions + i; - asn1cSequenceAdd(ie3->value.choice.PDUSessionResourceSetupListSURes.list, NGAP_PDUSessionResourceSetupItemSURes_t, item); - /* pDUSessionID */ - item->pDUSessionID = pdusession->pdusession_id; - - // PDU Session Resource Setup Response Transfer (Mandatory) - byte_array_t ba = encode_ngap_pdusession_setup_response_transfer(pdusession); - item->pDUSessionResourceSetupResponseTransfer.buf = ba.buf; - item->pDUSessionResourceSetupResponseTransfer.size = ba.len; - } - } - - /* optional */ - if (pdusession_setup_resp_p->nb_of_pdusessions_failed > 0) { - asn1cSequenceAdd(out->protocolIEs.list, NGAP_PDUSessionResourceSetupResponseIEs_t, ie); - ie->id = NGAP_ProtocolIE_ID_id_PDUSessionResourceFailedToSetupListSURes; - ie->criticality = NGAP_Criticality_ignore; - ie->value.present = NGAP_PDUSessionResourceSetupResponseIEs__value_PR_PDUSessionResourceFailedToSetupListSURes; - - for (int i = 0; i < pdusession_setup_resp_p->nb_of_pdusessions_failed; i++) { - pdusession_failed_t *pdusession_failed = pdusession_setup_resp_p->pdusessions_failed + i; - asn1cSequenceAdd(ie->value.choice.PDUSessionResourceFailedToSetupListSURes.list, NGAP_PDUSessionResourceFailedToSetupItemSURes_t, item); - NGAP_PDUSessionResourceSetupUnsuccessfulTransfer_t pdusessionUnTransfer_p = {0}; - - /* pDUSessionID */ - item->pDUSessionID = pdusession_failed->pdusession_id; - - /* cause */ - encode_ngap_cause(&pdusessionUnTransfer_p.cause, &pdusession_failed->cause); - NGAP_INFO("pdusession setup response: failed pdusession ID %ld\n", item->pDUSessionID); - - asn_encode_to_new_buffer_result_t res = asn_encode_to_new_buffer(NULL, ATS_ALIGNED_CANONICAL_PER, &asn_DEF_NGAP_PDUSessionResourceSetupUnsuccessfulTransfer, &pdusessionUnTransfer_p); - item->pDUSessionResourceSetupUnsuccessfulTransfer.buf = res.buffer; - item->pDUSessionResourceSetupUnsuccessfulTransfer.size = res.result.encoded; - - ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_PDUSessionResourceSetupUnsuccessfulTransfer, &pdusessionUnTransfer_p); - } - } - - /* optional */ - if (0) { - asn1cSequenceAdd(out->protocolIEs.list, NGAP_PDUSessionResourceSetupResponseIEs_t, ie); - ie->id = NGAP_ProtocolIE_ID_id_CriticalityDiagnostics; - ie->criticality = NGAP_Criticality_ignore; - ie->value.present = NGAP_PDUSessionResourceSetupResponseIEs__value_PR_CriticalityDiagnostics; - // ie->value.choice.CriticalityDiagnostics = ; - } - - if (ngap_gNB_encode_pdu(&pdu, &buffer, &length) < 0) { - NGAP_ERROR("Failed to encode uplink transport\n"); - /* Encode procedure has failed... */ - ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, &pdu); - return -1; - } - - /* UE associated signalling -> use the allocated stream */ - ngap_gNB_itti_send_sctp_data_req(ngap_gNB_instance_p->instance, ue_context_p->amf_ref->assoc_id, buffer, length, ue_context_p->tx_stream); - ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, &pdu); - return 0; -} - -//------------------------------------------------------------------------------ -int ngap_gNB_pdusession_modify_resp(instance_t instance, ngap_pdusession_modify_resp_t *pdusession_modify_resp_p) -//------------------------------------------------------------------------------ -{ - ngap_gNB_instance_t *ngap_gNB_instance_p = NULL; - struct ngap_gNB_ue_context_s *ue_context_p = NULL; - NGAP_NGAP_PDU_t pdu; - uint8_t *buffer = NULL; - uint32_t length; - - /* Retrieve the NGAP gNB instance associated with Mod_id */ - ngap_gNB_instance_p = ngap_gNB_get_instance(instance); - DevAssert(pdusession_modify_resp_p != NULL); - DevAssert(ngap_gNB_instance_p != NULL); - - if ((ue_context_p = ngap_get_ue_context(pdusession_modify_resp_p->gNB_ue_ngap_id)) == NULL) { - /* The context for this gNB ue ngap id doesn't exist in the map of gNB UEs */ - NGAP_WARN("Failed to find ue context associated with gNB ue ngap id: 0x%08x\n", pdusession_modify_resp_p->gNB_ue_ngap_id); - return -1; - } - - /* Uplink NAS transport can occur either during an ngap connected state - * or during initial attach (for example: NAS authentication). - */ - if (!(ue_context_p->ue_state == NGAP_UE_CONNECTED || ue_context_p->ue_state == NGAP_UE_WAITING_CSR)) { - NGAP_WARN( - "You are attempting to send NAS data over non-connected " - "gNB ue ngap id: %08x, current state: %d\n", - pdusession_modify_resp_p->gNB_ue_ngap_id, - ue_context_p->ue_state); - return -1; - } - - /* Prepare the NGAP message to encode */ - memset(&pdu, 0, sizeof(pdu)); - pdu.present = NGAP_NGAP_PDU_PR_successfulOutcome; - asn1cCalloc(pdu.choice.successfulOutcome, head); - head->procedureCode = NGAP_ProcedureCode_id_PDUSessionResourceModify; - head->criticality = NGAP_Criticality_reject; - head->value.present = NGAP_SuccessfulOutcome__value_PR_PDUSessionResourceModifyResponse; - NGAP_PDUSessionResourceModifyResponse_t *out = &head->value.choice.PDUSessionResourceModifyResponse; - /* mandatory */ - { - asn1cSequenceAdd(out->protocolIEs.list, NGAP_PDUSessionResourceModifyResponseIEs_t, ie); - ie = (NGAP_PDUSessionResourceModifyResponseIEs_t *)calloc(1, sizeof(NGAP_PDUSessionResourceModifyResponseIEs_t)); - ie->id = NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID; - ie->criticality = NGAP_Criticality_ignore; - ie->value.present = NGAP_PDUSessionResourceModifyResponseIEs__value_PR_AMF_UE_NGAP_ID; - asn_uint642INTEGER(&ie->value.choice.AMF_UE_NGAP_ID, pdusession_modify_resp_p->amf_ue_ngap_id); - asn1cSeqAdd(&out->protocolIEs.list, ie); - } - /* mandatory */ - { - asn1cSequenceAdd(out->protocolIEs.list, NGAP_PDUSessionResourceModifyResponseIEs_t, ie); - ie->id = NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID; - ie->criticality = NGAP_Criticality_ignore; - ie->value.present = NGAP_PDUSessionResourceModifyResponseIEs__value_PR_RAN_UE_NGAP_ID; - ie->value.choice.RAN_UE_NGAP_ID = pdusession_modify_resp_p->gNB_ue_ngap_id; - } - - /* PDUSessionResourceModifyListModRes optional */ - if (pdusession_modify_resp_p->nb_of_pdusessions > 0) { - asn1cSequenceAdd(out->protocolIEs.list, NGAP_PDUSessionResourceModifyResponseIEs_t, ie); - ie->id = NGAP_ProtocolIE_ID_id_PDUSessionResourceModifyListModRes; - ie->criticality = NGAP_Criticality_ignore; - ie->value.present = NGAP_PDUSessionResourceModifyResponseIEs__value_PR_PDUSessionResourceModifyListModRes; - - for (int i = 0; i < pdusession_modify_resp_p->nb_of_pdusessions; i++) { - asn1cSequenceAdd(ie->value.choice.PDUSessionResourceModifyListModRes.list, NGAP_PDUSessionResourceModifyItemModRes_t, item); - item->pDUSessionID = pdusession_modify_resp_p->pdusessions[i].pdusession_id; - - NGAP_PDUSessionResourceModifyResponseTransfer_t transfer = {0}; - asn1cCalloc(transfer.qosFlowAddOrModifyResponseList, tmp); - - for (int qos_flow_index = 0; qos_flow_index < pdusession_modify_resp_p->pdusessions[i].nb_of_qos_flow; qos_flow_index++) { - asn1cSequenceAdd(tmp->list, NGAP_QosFlowAddOrModifyResponseItem_t, qos); - qos->qosFlowIdentifier = pdusession_modify_resp_p->pdusessions[i].qos[qos_flow_index].qfi; - } - asn_encode_to_new_buffer_result_t res = {0}; - res = asn_encode_to_new_buffer(NULL, ATS_ALIGNED_CANONICAL_PER, &asn_DEF_NGAP_PDUSessionResourceModifyResponseTransfer, &transfer); - item->pDUSessionResourceModifyResponseTransfer.buf = res.buffer; - item->pDUSessionResourceModifyResponseTransfer.size = res.result.encoded; - - ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_PDUSessionResourceModifyResponseTransfer, &transfer); - - NGAP_DEBUG("pdusession_modify_resp: modified pdusession ID %ld\n", item->pDUSessionID); - } - } - - /* optional */ - if (pdusession_modify_resp_p->nb_of_pdusessions_failed > 0) { - asn1cSequenceAdd(out->protocolIEs.list, NGAP_PDUSessionResourceModifyResponseIEs_t, ie); - ie->id = NGAP_ProtocolIE_ID_id_PDUSessionResourceFailedToModifyListModRes; - ie->criticality = NGAP_Criticality_ignore; - ie->value.present = NGAP_PDUSessionResourceModifyResponseIEs__value_PR_PDUSessionResourceFailedToModifyListModRes; - - for (int i = 0; i < pdusession_modify_resp_p->nb_of_pdusessions_failed; i++) { - asn1cSequenceAdd(ie->value.choice.PDUSessionResourceFailedToModifyListModRes.list, NGAP_PDUSessionResourceFailedToModifyItemModRes_t, item); - item->pDUSessionID = pdusession_modify_resp_p->pdusessions_failed[i].pdusession_id; - - NGAP_PDUSessionResourceModifyUnsuccessfulTransfer_t pdusessionTransfer = {0}; - - // NGAP cause - encode_ngap_cause(&pdusessionTransfer.cause, &pdusession_modify_resp_p->pdusessions_failed[i].cause); - - asn_encode_to_new_buffer_result_t res = {0}; - res = asn_encode_to_new_buffer(NULL, ATS_ALIGNED_CANONICAL_PER, &asn_DEF_NGAP_PDUSessionResourceModifyUnsuccessfulTransfer, &pdusessionTransfer); - item->pDUSessionResourceModifyUnsuccessfulTransfer.buf = res.buffer; - item->pDUSessionResourceModifyUnsuccessfulTransfer.size = res.result.encoded; - - ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_PDUSessionResourceModifyUnsuccessfulTransfer, &pdusessionTransfer); - - NGAP_INFO("pdusession_modify_resp: failed pdusession ID %ld\n", item->pDUSessionID); - } - } - - /* optional */ - if (0) { - asn1cSequenceAdd(out->protocolIEs.list, NGAP_PDUSessionResourceModifyResponseIEs_t, ie); - ie->id = NGAP_ProtocolIE_ID_id_CriticalityDiagnostics; - ie->criticality = NGAP_Criticality_ignore; - ie->value.present = NGAP_PDUSessionResourceModifyResponseIEs__value_PR_CriticalityDiagnostics; - // ie->value.choice.CriticalityDiagnostics = ; - } - - if (ngap_gNB_encode_pdu(&pdu, &buffer, &length) < 0) { - NGAP_ERROR("Failed to encode uplink transport\n"); - /* Encode procedure has failed... */ - ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, &pdu); - return -1; - } - - /* UE associated signalling -> use the allocated stream */ - ngap_gNB_itti_send_sctp_data_req(ngap_gNB_instance_p->instance, ue_context_p->amf_ref->assoc_id, buffer, length, ue_context_p->tx_stream); - - ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, &pdu); - return 0; -} -//------------------------------------------------------------------------------ -int ngap_gNB_pdusession_release_resp(instance_t instance, ngap_pdusession_release_resp_t *pdusession_release_resp_p) -//------------------------------------------------------------------------------ -{ - ngap_gNB_instance_t *ngap_gNB_instance_p = NULL; - struct ngap_gNB_ue_context_s *ue_context_p = NULL; - NGAP_NGAP_PDU_t pdu; - uint8_t *buffer = NULL; - uint32_t length; - int i; - /* Retrieve the NGAP gNB instance associated with Mod_id */ - ngap_gNB_instance_p = ngap_gNB_get_instance(instance); - DevAssert(pdusession_release_resp_p != NULL); - DevAssert(ngap_gNB_instance_p != NULL); - - if ((ue_context_p = ngap_get_ue_context(pdusession_release_resp_p->gNB_ue_ngap_id)) == NULL) { - /* The context for this gNB ue ngap id doesn't exist in the map of gNB UEs */ - NGAP_WARN("Failed to find ue context associated with gNB ue ngap id: 0x%08x\n", pdusession_release_resp_p->gNB_ue_ngap_id); - return -1; - } - - /* Prepare the NGAP message to encode */ - memset(&pdu, 0, sizeof(pdu)); - pdu.present = NGAP_NGAP_PDU_PR_successfulOutcome; - asn1cCalloc(pdu.choice.successfulOutcome, head); - head->procedureCode = NGAP_ProcedureCode_id_PDUSessionResourceRelease; - head->criticality = NGAP_Criticality_reject; - head->value.present = NGAP_SuccessfulOutcome__value_PR_PDUSessionResourceReleaseResponse; - NGAP_PDUSessionResourceReleaseResponse_t *out = &head->value.choice.PDUSessionResourceReleaseResponse; - /* mandatory */ - { - asn1cSequenceAdd(out->protocolIEs.list, NGAP_PDUSessionResourceReleaseResponseIEs_t, 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; - asn_uint642INTEGER(&ie->value.choice.AMF_UE_NGAP_ID, ue_context_p->amf_ue_ngap_id); - } - /* mandatory */ - { - asn1cSequenceAdd(out->protocolIEs.list, NGAP_PDUSessionResourceReleaseResponseIEs_t, 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; - ie->value.choice.RAN_UE_NGAP_ID = pdusession_release_resp_p->gNB_ue_ngap_id; - } - - /* PDU Session Resource Released List (mandatory) */ - { - asn1cSequenceAdd(out->protocolIEs.list, NGAP_PDUSessionResourceReleaseResponseIEs_t, ie); - ie->id = NGAP_ProtocolIE_ID_id_PDUSessionResourceReleasedListRelRes; - ie->criticality = NGAP_Criticality_ignore; - ie->value.present = NGAP_PDUSessionResourceReleaseResponseIEs__value_PR_PDUSessionResourceReleasedListRelRes; - - for (i = 0; i < pdusession_release_resp_p->nb_of_pdusessions_released; i++) { - NGAP_PDUSessionResourceReleasedListRelRes_t *list = &ie->value.choice.PDUSessionResourceReleasedListRelRes; - asn1cSequenceAdd(list->list, NGAP_PDUSessionResourceReleasedItemRelRes_t, item); - pdusession_release_t *r = &pdusession_release_resp_p->pdusession_release[i]; - /* PDU Session ID (mandatory) */ - item->pDUSessionID = r->pdusession_id; - /* PDU Session Resource Release Response Transfer (mandatory) */ - // Empty transfer is valid since Secondary RAT Usage Information is optional and not used - byte_array_t transfer = encode_ngap_pdusession_release_response_transfer(); - OCTET_STRING_fromBuf(&item->pDUSessionResourceReleaseResponseTransfer, (const char *)transfer.buf, transfer.len); - free_byte_array(transfer); - NGAP_DEBUG("PDU Session Resource Release Response: pdusession ID %ld\n", item->pDUSessionID); - } - } - - if (ngap_gNB_encode_pdu(&pdu, &buffer, &length) < 0) { - NGAP_ERROR("Failed to encode release response\n"); - /* Encode procedure has failed... */ - ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, &pdu); - return -1; - } - - /* UE associated signalling -> use the allocated stream */ - ngap_gNB_itti_send_sctp_data_req(ngap_gNB_instance_p->instance, ue_context_p->amf_ref->assoc_id, buffer, length, ue_context_p->tx_stream); - NGAP_INFO("pdusession_release_response sended gNB_UE_NGAP_ID %u amf_ue_ngap_id %lu nb_of_pdusessions_released %d \n", - pdusession_release_resp_p->gNB_ue_ngap_id, - (uint64_t)ue_context_p->amf_ue_ngap_id, - pdusession_release_resp_p->nb_of_pdusessions_released); - - ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, &pdu); - return 0; -} - diff --git a/openair3/NGAP/ngap_gNB_nas_procedures.h b/openair3/NGAP/ngap_gNB_nas_procedures.h index 5189e6b311..38a9648bbb 100644 --- a/openair3/NGAP/ngap_gNB_nas_procedures.h +++ b/openair3/NGAP/ngap_gNB_nas_procedures.h @@ -54,13 +54,4 @@ int ngap_gNB_initial_ctxt_fail(instance_t instance, ngap_initial_context_setup_f int ngap_gNB_ue_capabilities(instance_t instance, ngap_ue_cap_info_ind_t *ue_cap_info_ind_p); -int ngap_gNB_pdusession_setup_resp(instance_t instance, - ngap_pdusession_setup_resp_t *pdusession_setup_resp_p); - -int ngap_gNB_pdusession_modify_resp(instance_t instance, - ngap_pdusession_modify_resp_t *pdusession_modify_resp_p); - -int ngap_gNB_pdusession_release_resp(instance_t instance, - ngap_pdusession_release_resp_t *pdusession_release_resp_p); - #endif /* NGAP_GNB_NAS_PROCEDURES_H_ */ diff --git a/openair3/NGAP/ngap_gNB_pdu_session_management.c b/openair3/NGAP/ngap_gNB_pdu_session_management.c new file mode 100644 index 0000000000..7f4ec2d6da --- /dev/null +++ b/openair3/NGAP/ngap_gNB_pdu_session_management.c @@ -0,0 +1,425 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include "ngap_gNB_pdu_session_management.h" +#include +#include +#include +#include "INTEGER.h" +#include "ngap_msg_includes.h" +#include "OCTET_STRING.h" +#include "asn_application.h" +#include "assertions.h" +#include "conversions.h" +#include "ngap_common.h" +#include "ngap_gNB_encoder.h" +#include "ngap_gNB_itti_messaging.h" +#include "ngap_gNB_ue_context.h" +#include "ngap_gNB_management_procedures.h" +#include "oai_asn1.h" +#include "ds/byte_array.h" + +int ngap_gNB_pdusession_setup_resp(instance_t instance, ngap_pdusession_setup_resp_t *pdusession_setup_resp_p) +{ + ngap_gNB_instance_t *ngap_gNB_instance_p = NULL; + struct ngap_gNB_ue_context_s *ue_context_p = NULL; + NGAP_NGAP_PDU_t pdu = {0}; + uint8_t *buffer = NULL; + uint32_t length; + + /* Retrieve the NGAP gNB instance associated with Mod_id */ + ngap_gNB_instance_p = ngap_gNB_get_instance(instance); + DevAssert(pdusession_setup_resp_p != NULL); + DevAssert(ngap_gNB_instance_p != NULL); + + if ((ue_context_p = ngap_get_ue_context(pdusession_setup_resp_p->gNB_ue_ngap_id)) == NULL) { + /* The context for this gNB ue ngap id doesn't exist in the map of gNB UEs */ + NGAP_WARN("Failed to find ue context associated with gNB ue ngap id: 0x%08x\n", pdusession_setup_resp_p->gNB_ue_ngap_id); + return -1; + } + + /* Uplink NAS transport can occur either during an ngap connected state + * or during initial attach (for example: NAS authentication). + */ + if (!(ue_context_p->ue_state == NGAP_UE_CONNECTED || ue_context_p->ue_state == NGAP_UE_WAITING_CSR)) { + NGAP_WARN( + "You are attempting to send NAS data over non-connected " + "gNB ue ngap id: %08x, current state: %d\n", + pdusession_setup_resp_p->gNB_ue_ngap_id, + ue_context_p->ue_state); + return -1; + } + + /* Prepare the NGAP message to encode */ + pdu.present = NGAP_NGAP_PDU_PR_successfulOutcome; + asn1cCalloc(pdu.choice.successfulOutcome, successfulOutcome); + successfulOutcome->procedureCode = NGAP_ProcedureCode_id_PDUSessionResourceSetup; + successfulOutcome->criticality = NGAP_Criticality_reject; + successfulOutcome->value.present = NGAP_SuccessfulOutcome__value_PR_PDUSessionResourceSetupResponse; + NGAP_PDUSessionResourceSetupResponse_t *out = &successfulOutcome->value.choice.PDUSessionResourceSetupResponse; + /* mandatory */ + { + asn1cSequenceAdd(out->protocolIEs.list, NGAP_PDUSessionResourceSetupResponseIEs_t, ie); + ie->id = NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID; + ie->criticality = NGAP_Criticality_ignore; + ie->value.present = NGAP_PDUSessionResourceSetupResponseIEs__value_PR_AMF_UE_NGAP_ID; + asn_uint642INTEGER(&ie->value.choice.AMF_UE_NGAP_ID, ue_context_p->amf_ue_ngap_id); + } + /* mandatory */ + { + asn1cSequenceAdd(out->protocolIEs.list, NGAP_PDUSessionResourceSetupResponseIEs_t, ie); + ie->id = NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID; + ie->criticality = NGAP_Criticality_ignore; + ie->value.present = NGAP_PDUSessionResourceSetupResponseIEs__value_PR_RAN_UE_NGAP_ID; + ie->value.choice.RAN_UE_NGAP_ID = pdusession_setup_resp_p->gNB_ue_ngap_id; + } + + /* optional */ + if (pdusession_setup_resp_p->nb_of_pdusessions > 0) { + asn1cSequenceAdd(out->protocolIEs.list, NGAP_PDUSessionResourceSetupResponseIEs_t, ie3); + ie3->id = NGAP_ProtocolIE_ID_id_PDUSessionResourceSetupListSURes; + ie3->criticality = NGAP_Criticality_ignore; + ie3->value.present = NGAP_PDUSessionResourceSetupResponseIEs__value_PR_PDUSessionResourceSetupListSURes; + + for (int i = 0; i < pdusession_setup_resp_p->nb_of_pdusessions; i++) { + pdusession_setup_t *pdusession = pdusession_setup_resp_p->pdusessions + i; + asn1cSequenceAdd(ie3->value.choice.PDUSessionResourceSetupListSURes.list, NGAP_PDUSessionResourceSetupItemSURes_t, item); + /* pDUSessionID */ + item->pDUSessionID = pdusession->pdusession_id; + + // PDU Session Resource Setup Response Transfer (Mandatory) + byte_array_t ba = encode_ngap_pdusession_setup_response_transfer(pdusession); + item->pDUSessionResourceSetupResponseTransfer.buf = ba.buf; + item->pDUSessionResourceSetupResponseTransfer.size = ba.len; + } + } + + /* optional */ + if (pdusession_setup_resp_p->nb_of_pdusessions_failed > 0) { + asn1cSequenceAdd(out->protocolIEs.list, NGAP_PDUSessionResourceSetupResponseIEs_t, ie); + ie->id = NGAP_ProtocolIE_ID_id_PDUSessionResourceFailedToSetupListSURes; + ie->criticality = NGAP_Criticality_ignore; + ie->value.present = NGAP_PDUSessionResourceSetupResponseIEs__value_PR_PDUSessionResourceFailedToSetupListSURes; + + for (int i = 0; i < pdusession_setup_resp_p->nb_of_pdusessions_failed; i++) { + pdusession_failed_t *pdusession_failed = pdusession_setup_resp_p->pdusessions_failed + i; + asn1cSequenceAdd(ie->value.choice.PDUSessionResourceFailedToSetupListSURes.list, + NGAP_PDUSessionResourceFailedToSetupItemSURes_t, + item); + NGAP_PDUSessionResourceSetupUnsuccessfulTransfer_t pdusessionUnTransfer_p = {0}; + + /* pDUSessionID */ + item->pDUSessionID = pdusession_failed->pdusession_id; + + /* cause */ + encode_ngap_cause(&pdusessionUnTransfer_p.cause, &pdusession_failed->cause); + NGAP_INFO("pdusession setup response: failed pdusession ID %ld\n", item->pDUSessionID); + + asn_encode_to_new_buffer_result_t res = asn_encode_to_new_buffer(NULL, + ATS_ALIGNED_CANONICAL_PER, + &asn_DEF_NGAP_PDUSessionResourceSetupUnsuccessfulTransfer, + &pdusessionUnTransfer_p); + item->pDUSessionResourceSetupUnsuccessfulTransfer.buf = res.buffer; + item->pDUSessionResourceSetupUnsuccessfulTransfer.size = res.result.encoded; + + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_PDUSessionResourceSetupUnsuccessfulTransfer, &pdusessionUnTransfer_p); + } + } + + /* optional */ + if (0) { + asn1cSequenceAdd(out->protocolIEs.list, NGAP_PDUSessionResourceSetupResponseIEs_t, ie); + ie->id = NGAP_ProtocolIE_ID_id_CriticalityDiagnostics; + ie->criticality = NGAP_Criticality_ignore; + ie->value.present = NGAP_PDUSessionResourceSetupResponseIEs__value_PR_CriticalityDiagnostics; + } + + if (ngap_gNB_encode_pdu(&pdu, &buffer, &length) < 0) { + NGAP_ERROR("Failed to encode uplink transport\n"); + /* Encode procedure has failed... */ + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, &pdu); + return -1; + } + + /* UE associated signalling -> use the allocated stream */ + ngap_gNB_itti_send_sctp_data_req(ngap_gNB_instance_p->instance, + ue_context_p->amf_ref->assoc_id, + buffer, + length, + ue_context_p->tx_stream); + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, &pdu); + return 0; +} + +int ngap_gNB_pdusession_modify_resp(instance_t instance, ngap_pdusession_modify_resp_t *pdusession_modify_resp_p) +{ + ngap_gNB_instance_t *ngap_gNB_instance_p = NULL; + struct ngap_gNB_ue_context_s *ue_context_p = NULL; + NGAP_NGAP_PDU_t pdu; + uint8_t *buffer = NULL; + uint32_t length; + + /* Retrieve the NGAP gNB instance associated with Mod_id */ + ngap_gNB_instance_p = ngap_gNB_get_instance(instance); + DevAssert(pdusession_modify_resp_p != NULL); + DevAssert(ngap_gNB_instance_p != NULL); + + if ((ue_context_p = ngap_get_ue_context(pdusession_modify_resp_p->gNB_ue_ngap_id)) == NULL) { + /* The context for this gNB ue ngap id doesn't exist in the map of gNB UEs */ + NGAP_WARN("Failed to find ue context associated with gNB ue ngap id: 0x%08x\n", pdusession_modify_resp_p->gNB_ue_ngap_id); + return -1; + } + + /* Uplink NAS transport can occur either during an ngap connected state + * or during initial attach (for example: NAS authentication). + */ + if (!(ue_context_p->ue_state == NGAP_UE_CONNECTED || ue_context_p->ue_state == NGAP_UE_WAITING_CSR)) { + NGAP_WARN( + "You are attempting to send NAS data over non-connected " + "gNB ue ngap id: %08x, current state: %d\n", + pdusession_modify_resp_p->gNB_ue_ngap_id, + ue_context_p->ue_state); + return -1; + } + + /* Prepare the NGAP message to encode */ + memset(&pdu, 0, sizeof(pdu)); + pdu.present = NGAP_NGAP_PDU_PR_successfulOutcome; + asn1cCalloc(pdu.choice.successfulOutcome, head); + head->procedureCode = NGAP_ProcedureCode_id_PDUSessionResourceModify; + head->criticality = NGAP_Criticality_reject; + head->value.present = NGAP_SuccessfulOutcome__value_PR_PDUSessionResourceModifyResponse; + NGAP_PDUSessionResourceModifyResponse_t *out = &head->value.choice.PDUSessionResourceModifyResponse; + /* mandatory */ + { + asn1cSequenceAdd(out->protocolIEs.list, NGAP_PDUSessionResourceModifyResponseIEs_t, ie); + ie = (NGAP_PDUSessionResourceModifyResponseIEs_t *)calloc(1, sizeof(NGAP_PDUSessionResourceModifyResponseIEs_t)); + ie->id = NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID; + ie->criticality = NGAP_Criticality_ignore; + ie->value.present = NGAP_PDUSessionResourceModifyResponseIEs__value_PR_AMF_UE_NGAP_ID; + asn_uint642INTEGER(&ie->value.choice.AMF_UE_NGAP_ID, pdusession_modify_resp_p->amf_ue_ngap_id); + asn1cSeqAdd(&out->protocolIEs.list, ie); + } + /* mandatory */ + { + asn1cSequenceAdd(out->protocolIEs.list, NGAP_PDUSessionResourceModifyResponseIEs_t, ie); + ie->id = NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID; + ie->criticality = NGAP_Criticality_ignore; + ie->value.present = NGAP_PDUSessionResourceModifyResponseIEs__value_PR_RAN_UE_NGAP_ID; + ie->value.choice.RAN_UE_NGAP_ID = pdusession_modify_resp_p->gNB_ue_ngap_id; + } + + /* PDUSessionResourceModifyListModRes optional */ + if (pdusession_modify_resp_p->nb_of_pdusessions > 0) { + asn1cSequenceAdd(out->protocolIEs.list, NGAP_PDUSessionResourceModifyResponseIEs_t, ie); + ie->id = NGAP_ProtocolIE_ID_id_PDUSessionResourceModifyListModRes; + ie->criticality = NGAP_Criticality_ignore; + ie->value.present = NGAP_PDUSessionResourceModifyResponseIEs__value_PR_PDUSessionResourceModifyListModRes; + + for (int i = 0; i < pdusession_modify_resp_p->nb_of_pdusessions; i++) { + asn1cSequenceAdd(ie->value.choice.PDUSessionResourceModifyListModRes.list, NGAP_PDUSessionResourceModifyItemModRes_t, item); + item->pDUSessionID = pdusession_modify_resp_p->pdusessions[i].pdusession_id; + + NGAP_PDUSessionResourceModifyResponseTransfer_t transfer = {0}; + asn1cCalloc(transfer.qosFlowAddOrModifyResponseList, tmp); + + for (int qos_flow_index = 0; qos_flow_index < pdusession_modify_resp_p->pdusessions[i].nb_of_qos_flow; qos_flow_index++) { + asn1cSequenceAdd(tmp->list, NGAP_QosFlowAddOrModifyResponseItem_t, qos); + qos->qosFlowIdentifier = pdusession_modify_resp_p->pdusessions[i].qos[qos_flow_index].qfi; + } + asn_encode_to_new_buffer_result_t res = {0}; + res = asn_encode_to_new_buffer(NULL, + ATS_ALIGNED_CANONICAL_PER, + &asn_DEF_NGAP_PDUSessionResourceModifyResponseTransfer, + &transfer); + item->pDUSessionResourceModifyResponseTransfer.buf = res.buffer; + item->pDUSessionResourceModifyResponseTransfer.size = res.result.encoded; + + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_PDUSessionResourceModifyResponseTransfer, &transfer); + + NGAP_DEBUG("pdusession_modify_resp: modified pdusession ID %ld\n", item->pDUSessionID); + } + } + + /* optional */ + if (pdusession_modify_resp_p->nb_of_pdusessions_failed > 0) { + asn1cSequenceAdd(out->protocolIEs.list, NGAP_PDUSessionResourceModifyResponseIEs_t, ie); + ie->id = NGAP_ProtocolIE_ID_id_PDUSessionResourceFailedToModifyListModRes; + ie->criticality = NGAP_Criticality_ignore; + ie->value.present = NGAP_PDUSessionResourceModifyResponseIEs__value_PR_PDUSessionResourceFailedToModifyListModRes; + + for (int i = 0; i < pdusession_modify_resp_p->nb_of_pdusessions_failed; i++) { + asn1cSequenceAdd(ie->value.choice.PDUSessionResourceFailedToModifyListModRes.list, + NGAP_PDUSessionResourceFailedToModifyItemModRes_t, + item); + item->pDUSessionID = pdusession_modify_resp_p->pdusessions_failed[i].pdusession_id; + + NGAP_PDUSessionResourceModifyUnsuccessfulTransfer_t pdusessionTransfer = {0}; + + // NGAP cause + encode_ngap_cause(&pdusessionTransfer.cause, &pdusession_modify_resp_p->pdusessions_failed[i].cause); + + asn_encode_to_new_buffer_result_t res = {0}; + NGAP_PDUSessionResourceModifyUnsuccessfulTransfer_t *pdusessionTransfer_p = NULL; + res = asn_encode_to_new_buffer(NULL, + ATS_ALIGNED_CANONICAL_PER, + &asn_DEF_NGAP_PDUSessionResourceModifyUnsuccessfulTransfer, + &pdusessionTransfer); + item->pDUSessionResourceModifyUnsuccessfulTransfer.buf = res.buffer; + item->pDUSessionResourceModifyUnsuccessfulTransfer.size = res.result.encoded; + + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_PDUSessionResourceModifyUnsuccessfulTransfer, pdusessionTransfer_p); + + NGAP_INFO("pdusession_modify_resp: failed pdusession ID %ld\n", item->pDUSessionID); + } + } + + /* optional */ + if (0) { + asn1cSequenceAdd(out->protocolIEs.list, NGAP_PDUSessionResourceModifyResponseIEs_t, ie); + ie->id = NGAP_ProtocolIE_ID_id_CriticalityDiagnostics; + ie->criticality = NGAP_Criticality_ignore; + ie->value.present = NGAP_PDUSessionResourceModifyResponseIEs__value_PR_CriticalityDiagnostics; + } + + if (ngap_gNB_encode_pdu(&pdu, &buffer, &length) < 0) { + NGAP_ERROR("Failed to encode uplink transport\n"); + /* Encode procedure has failed... */ + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, &pdu); + return -1; + } + + /* UE associated signalling -> use the allocated stream */ + ngap_gNB_itti_send_sctp_data_req(ngap_gNB_instance_p->instance, + ue_context_p->amf_ref->assoc_id, + buffer, + length, + ue_context_p->tx_stream); + + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, &pdu); + return 0; +} + +/** @brief PDU Session Resource Release Response Transfer encoding (9.3.4.21 3GPP TS 38.413) + * The transfer structure contains only an optional Secondary RAT Usage Information IE. + * Since we don't use secondary RAT (MR-DC), we encode an empty structure. */ +static byte_array_t encode_ngap_pdusession_release_response_transfer(void) +{ + NGAP_PDUSessionResourceReleaseResponseTransfer_t pdusessionTransfer = {0}; + + // Encode + asn_encode_to_new_buffer_result_t res = asn_encode_to_new_buffer(NULL, + ATS_ALIGNED_CANONICAL_PER, + &asn_DEF_NGAP_PDUSessionResourceReleaseResponseTransfer, + &pdusessionTransfer); + AssertFatal(res.buffer, "ASN1 message encoding failed (%s, %lu)!\n", res.result.failed_type->name, res.result.encoded); + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_PDUSessionResourceReleaseResponseTransfer, &pdusessionTransfer); + byte_array_t out = {.buf = res.buffer, .len = res.result.encoded}; + return out; +} + +int ngap_gNB_pdusession_release_resp(instance_t instance, ngap_pdusession_release_resp_t *pdusession_release_resp_p) +{ + ngap_gNB_instance_t *ngap_gNB_instance_p = NULL; + struct ngap_gNB_ue_context_s *ue_context_p = NULL; + NGAP_NGAP_PDU_t pdu; + uint8_t *buffer = NULL; + uint32_t length; + int i; + /* Retrieve the NGAP gNB instance associated with Mod_id */ + ngap_gNB_instance_p = ngap_gNB_get_instance(instance); + DevAssert(pdusession_release_resp_p != NULL); + DevAssert(ngap_gNB_instance_p != NULL); + + if ((ue_context_p = ngap_get_ue_context(pdusession_release_resp_p->gNB_ue_ngap_id)) == NULL) { + /* The context for this gNB ue ngap id doesn't exist in the map of gNB UEs */ + NGAP_WARN("Failed to find ue context associated with gNB ue ngap id: 0x%08x\n", pdusession_release_resp_p->gNB_ue_ngap_id); + return -1; + } + + /* Prepare the NGAP message to encode */ + memset(&pdu, 0, sizeof(pdu)); + pdu.present = NGAP_NGAP_PDU_PR_successfulOutcome; + asn1cCalloc(pdu.choice.successfulOutcome, head); + head->procedureCode = NGAP_ProcedureCode_id_PDUSessionResourceRelease; + head->criticality = NGAP_Criticality_reject; + head->value.present = NGAP_SuccessfulOutcome__value_PR_PDUSessionResourceReleaseResponse; + NGAP_PDUSessionResourceReleaseResponse_t *out = &head->value.choice.PDUSessionResourceReleaseResponse; + /* mandatory */ + { + asn1cSequenceAdd(out->protocolIEs.list, NGAP_PDUSessionResourceReleaseResponseIEs_t, 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; + asn_uint642INTEGER(&ie->value.choice.AMF_UE_NGAP_ID, ue_context_p->amf_ue_ngap_id); + } + /* mandatory */ + { + asn1cSequenceAdd(out->protocolIEs.list, NGAP_PDUSessionResourceReleaseResponseIEs_t, 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; + ie->value.choice.RAN_UE_NGAP_ID = pdusession_release_resp_p->gNB_ue_ngap_id; + } + + /* PDU Session Resource Released List (mandatory) */ + { + asn1cSequenceAdd(out->protocolIEs.list, NGAP_PDUSessionResourceReleaseResponseIEs_t, ie); + ie->id = NGAP_ProtocolIE_ID_id_PDUSessionResourceReleasedListRelRes; + ie->criticality = NGAP_Criticality_ignore; + ie->value.present = NGAP_PDUSessionResourceReleaseResponseIEs__value_PR_PDUSessionResourceReleasedListRelRes; + + for (i = 0; i < pdusession_release_resp_p->nb_of_pdusessions_released; i++) { + NGAP_PDUSessionResourceReleasedListRelRes_t *list = &ie->value.choice.PDUSessionResourceReleasedListRelRes; + asn1cSequenceAdd(list->list, NGAP_PDUSessionResourceReleasedItemRelRes_t, item); + pdusession_release_t *r = &pdusession_release_resp_p->pdusession_release[i]; + /* PDU Session ID (mandatory) */ + item->pDUSessionID = r->pdusession_id; + /* PDU Session Resource Release Response Transfer (mandatory) */ + // Empty transfer is valid since Secondary RAT Usage Information is optional and not used + byte_array_t transfer = encode_ngap_pdusession_release_response_transfer(); + OCTET_STRING_fromBuf(&item->pDUSessionResourceReleaseResponseTransfer, (const char *)transfer.buf, transfer.len); + free_byte_array(transfer); + NGAP_DEBUG("PDU Session Resource Release Response: pdusession ID %ld\n", item->pDUSessionID); + } + } + + if (ngap_gNB_encode_pdu(&pdu, &buffer, &length) < 0) { + NGAP_ERROR("Failed to encode release response\n"); + /* Encode procedure has failed... */ + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, &pdu); + return -1; + } + + /* UE associated signalling -> use the allocated stream */ + ngap_gNB_itti_send_sctp_data_req(ngap_gNB_instance_p->instance, + ue_context_p->amf_ref->assoc_id, + buffer, + length, + ue_context_p->tx_stream); + NGAP_INFO("pdusession_release_response sended gNB_UE_NGAP_ID %u amf_ue_ngap_id %lu nb_of_pdusessions_released %d \n", + pdusession_release_resp_p->gNB_ue_ngap_id, + (uint64_t)ue_context_p->amf_ue_ngap_id, + pdusession_release_resp_p->nb_of_pdusessions_released); + + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, &pdu); + return 0; +} diff --git a/openair3/NGAP/ngap_gNB_pdu_session_management.h b/openair3/NGAP/ngap_gNB_pdu_session_management.h new file mode 100644 index 0000000000..3e50d1bec1 --- /dev/null +++ b/openair3/NGAP/ngap_gNB_pdu_session_management.h @@ -0,0 +1,36 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef NGAP_GNB_PDU_SESSION_MANAGEMENT_H_ +#define NGAP_GNB_PDU_SESSION_MANAGEMENT_H_ + +#include +#include "assertions.h" +#include "ngap_messages_types.h" +#include "ngap_msg_includes.h" + +int ngap_gNB_pdusession_setup_resp(instance_t instance, ngap_pdusession_setup_resp_t *pdusession_setup_resp_p); + +int ngap_gNB_pdusession_modify_resp(instance_t instance, ngap_pdusession_modify_resp_t *pdusession_modify_resp_p); + +int ngap_gNB_pdusession_release_resp(instance_t instance, ngap_pdusession_release_resp_t *pdusession_release_resp_p); + +#endif /* NGAP_GNB_PDU_SESSION_MANAGEMENT_H_ */