Refactor (NGAP): extract PDU session management procedures to dedicated library

PDU session related NGAP messages do not belong to NAS procedures lib.

* Create ngap_gNB_pdu_session_management.c and .h
* Move out ngap_gNB_pdusession_setup_resp, ngap_gNB_pdusession_modify_resp,
  ngap_gNB_pdusession_release_resp from ngap_gNB_nas_procedures.c
* Move encode_ngap_pdusession_setup_response_transfer to ngap_common.c:
  this transfer IE is common used both in PDU Session Management and
  Initial Context Setup, so it's moved to the common lib
* Add ngap_gNB_pdu_session_management.c to CMakeLists.txt
This commit is contained in:
Guido Casati
2026-02-17 12:25:58 +01:00
parent 563a0cfa61
commit e062f40137
9 changed files with 505 additions and 419 deletions
+1
View File
@@ -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
+40
View File
@@ -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, &gtp->gTP_TEID);
tnl_to_bitstring(&gtp->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;
}
+1 -1
View File
@@ -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_ */
+1
View File
@@ -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"
+1
View File
@@ -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"
-409
View File
@@ -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, &gtp->gTP_TEID);
tnl_to_bitstring(&gtp->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;
}
-9
View File
@@ -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_ */
@@ -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 <stdint.h>
#include <string.h>
#include <arpa/inet.h>
#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;
}
@@ -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 <stdint.h>
#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_ */