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:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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_ */
|
||||
Reference in New Issue
Block a user