mirror of
https://gitlab.eurecom.fr/oai/openairinterface5g.git
synced 2026-07-13 04:30:28 +00:00
NGAP Path Switch Request: add encode and ITTI support
- Add a case in TASK_NGAP to support ITTI message from RRC to NGAP
- Add Path Switch Request message type definitions
- Implement encoder for Path Switch Request (3GPP TS 38.413v16.2.0 §9.2.3.8)
- RAN UE NGAP ID (M)
- Source AMF UE NGAP ID (M)
- User Location Information (M)
- UE Security Capabilities (M)
- PDU Session Resource to be Switched in Downlink List (M)
- Add required ASN.1 header includes for Path Switch Request IEs
Co-authored-by: Rakesh BB <rakesh.bb@fsid-iisc.in>
Signed-off-by: Venkatareddy Akumalla <venkatareddy.akumalla@openairinterface.org>
This commit is contained in:
@@ -53,6 +53,7 @@ MESSAGE_DEF(NGAP_HANDOVER_CANCEL, MESSAGE_PRIORITY_MED, ngap_handover_cancel_t,
|
||||
MESSAGE_DEF(NGAP_UL_RAN_STATUS_TRANSFER, MESSAGE_PRIORITY_MED, ngap_ran_status_transfer_t, ngap_ul_ran_status_transfer)
|
||||
MESSAGE_DEF(NGAP_DL_RAN_STATUS_TRANSFER, MESSAGE_PRIORITY_MED, ngap_ran_status_transfer_t, ngap_dl_ran_status_transfer)
|
||||
MESSAGE_DEF(NGAP_RECONNECT_TIMER, MESSAGE_PRIORITY_MED, IttiMsgText, ngap_gNB_amf_data)
|
||||
MESSAGE_DEF(NGAP_PATH_SWITCH_REQ, MESSAGE_PRIORITY_MED, ngap_path_switch_req_t, ngap_path_switch_req)
|
||||
|
||||
/* NGAP -> RRC messages */
|
||||
MESSAGE_DEF(NGAP_DOWNLINK_NAS , MESSAGE_PRIORITY_MED, ngap_downlink_nas_t , ngap_downlink_nas )
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
#define NGAP_HANDOVER_NOTIFY(mSGpTR) (mSGpTR)->ittiMsg.ngap_handover_notify
|
||||
#define NGAP_HANDOVER_CANCEL(mSGpTR) (mSGpTR)->ittiMsg.ngap_handover_cancel
|
||||
#define NGAP_HANDOVER_CANCEL_ACK(mSGpTR) (mSGpTR)->ittiMsg.ngap_handover_cancel_ack
|
||||
#define NGAP_PATH_SWITCH_REQ(mSGpTR) (mSGpTR)->ittiMsg.ngap_path_switch_req
|
||||
|
||||
#define NGAP_UE_CONTEXT_RELEASE_REQ(mSGpTR) (mSGpTR)->ittiMsg.ngap_ue_release_req
|
||||
#define NGAP_PDUSESSION_RELEASE_COMMAND(mSGpTR) (mSGpTR)->ittiMsg.ngap_pdusession_release_command
|
||||
@@ -669,6 +670,22 @@ typedef struct {
|
||||
uint64_t amf_ue_ngap_id;
|
||||
} ngap_handover_cancel_ack_t;
|
||||
|
||||
/* Path Switch Request 9.2.3.8 3GPP TS 38.413 */
|
||||
typedef struct ngap_path_switch_req_s {
|
||||
// RAN UE NGAP ID
|
||||
uint32_t gNB_ue_ngap_id;
|
||||
// Source AMF UE NGAP ID
|
||||
uint64_t amf_ue_ngap_id;
|
||||
// User Location Information
|
||||
user_location_information_t user_info;
|
||||
// UE Security Capabilities
|
||||
ngap_security_capabilities_t security_capabilities;
|
||||
// Number of pdusession to be switched in the downlink list
|
||||
uint16_t nb_of_pdusessions;
|
||||
// List of PDU Session Resource to be Switched in Downlink
|
||||
pdusession_setup_t pdusessions_tobeswitched[NR_MAX_NB_PDU_SESSIONS];
|
||||
} ngap_path_switch_req_t;
|
||||
|
||||
typedef struct ngap_ue_cap_info_ind_s {
|
||||
uint32_t gNB_ue_ngap_id;
|
||||
byte_array_t ue_radio_cap;
|
||||
|
||||
@@ -133,6 +133,14 @@ nssai_t decode_ngap_nssai(const NGAP_S_NSSAI_t *in)
|
||||
return nssai;
|
||||
}
|
||||
|
||||
void encode_ngap_security_capabilities(NGAP_UESecurityCapabilities_t *out, const ngap_security_capabilities_t *in)
|
||||
{
|
||||
ENCRALG_TO_BIT_STRING(in->nRencryption_algorithms, &out->nRencryptionAlgorithms);
|
||||
ENCRALG_TO_BIT_STRING(in->eUTRAencryption_algorithms, &out->eUTRAencryptionAlgorithms);
|
||||
INTPROTALG_TO_BIT_STRING(in->nRintegrity_algorithms, &out->nRintegrityProtectionAlgorithms);
|
||||
INTPROTALG_TO_BIT_STRING(in->eUTRAintegrity_algorithms, &out->eUTRAintegrityProtectionAlgorithms);
|
||||
}
|
||||
|
||||
ngap_security_capabilities_t decode_ngap_security_capabilities(const NGAP_UESecurityCapabilities_t *in)
|
||||
{
|
||||
ngap_security_capabilities_t out = {0};
|
||||
|
||||
@@ -41,6 +41,7 @@ pdusession_level_qos_parameter_t fill_qos(uint8_t qfi, const NGAP_QosFlowLevelQo
|
||||
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);
|
||||
void encode_ngap_security_capabilities(NGAP_UESecurityCapabilities_t *out, const ngap_security_capabilities_t *in);
|
||||
|
||||
bool eq_ngap_plmn(const plmn_id_t *a, const plmn_id_t *b);
|
||||
|
||||
|
||||
@@ -281,6 +281,56 @@ void ngap_gNB_handle_sctp_data_ind(sctp_data_ind_t *sctp_data_ind) {
|
||||
AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
|
||||
}
|
||||
|
||||
static int ngap_gNB_path_switch_request(instance_t instance, ngap_path_switch_req_t *msg)
|
||||
{
|
||||
DevAssert(msg != NULL);
|
||||
NGAP_DEBUG("Triggered Pathswitch Request\n");
|
||||
|
||||
/*Retrieve the NGAP gNB instance associated with Mod_id */
|
||||
ngap_gNB_instance_t *ngap_gNB_instance_p = ngap_gNB_get_instance(instance);
|
||||
DevAssert(ngap_gNB_instance_p != NULL);
|
||||
|
||||
NGAP_NGAP_PDU_t *pdu = encode_ng_path_switch_request(msg);
|
||||
DevAssert(pdu != NULL);
|
||||
|
||||
if (LOG_DEBUGFLAG(DEBUG_ASN1))
|
||||
xer_fprint(stdout, &asn_DEF_NGAP_NGAP_PDU, pdu);
|
||||
|
||||
byte_array_t out = { .buf = NULL, .len = 0 };
|
||||
if (ngap_gNB_encode_pdu(pdu, &out.buf, (uint32_t *)&out.len) < 0) {
|
||||
NGAP_ERROR("Failed to encode Path Switch Request message\n");
|
||||
ASN_STRUCT_FREE(asn_DEF_NGAP_NGAP_PDU, pdu);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ngap_gNB_amf_data_t *amf_ref = ngap_gNB_get_AMF_from_instance(ngap_gNB_instance_p);
|
||||
if (!amf_ref) {
|
||||
NGAP_ERROR("Failed to fetch AMF for current NGAP instance\n");
|
||||
ASN_STRUCT_FREE(asn_DEF_NGAP_NGAP_PDU, pdu);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Create and then store the NGAP UE context
|
||||
ngap_gNB_ue_context_t ue_context_p = {
|
||||
.amf_ref = amf_ref,
|
||||
.gNB_ue_ngap_id = msg->gNB_ue_ngap_id,
|
||||
.amf_ue_ngap_id = msg->amf_ue_ngap_id,
|
||||
.gNB_instance = ngap_gNB_instance_p,
|
||||
.ue_state = NGAP_UE_CONNECTED,
|
||||
};
|
||||
ngap_store_ue_context(&ue_context_p);
|
||||
|
||||
/* 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,
|
||||
out.buf,
|
||||
out.len,
|
||||
ue_context_p.tx_stream);
|
||||
NGAP_INFO("Sent Path Switch Request to AMF\n");
|
||||
ASN_STRUCT_FREE(asn_DEF_NGAP_NGAP_PDU, pdu);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @brief UE Mobility Management: callback for Handover Required */
|
||||
int ngap_handover_required(instance_t instance, ngap_handover_required_t *msg)
|
||||
{
|
||||
@@ -613,6 +663,10 @@ void *ngap_gNB_process_itti_msg(void *notUsed)
|
||||
ngap_gNB_pdusession_release_resp(instance, &NGAP_PDUSESSION_RELEASE_RESPONSE(received_msg));
|
||||
break;
|
||||
|
||||
case NGAP_PATH_SWITCH_REQ:
|
||||
ngap_gNB_path_switch_request(instance, &NGAP_PATH_SWITCH_REQ(received_msg));
|
||||
break;
|
||||
|
||||
case NGAP_HANDOVER_REQUIRED:
|
||||
if (ngap_handover_required(instance, &NGAP_HANDOVER_REQUIRED(received_msg)) < 0) {
|
||||
NGAP_ERROR("Handover Required failure: indication to RRC is not sent!\n");
|
||||
|
||||
@@ -732,3 +732,95 @@ NGAP_NGAP_PDU_t *encode_ng_ul_ran_status_transfer(const ngap_ran_status_transfer
|
||||
|
||||
return pdu;
|
||||
}
|
||||
|
||||
/** @brief Encode NGAP Path Switch Request (9.2.3.8 3GPP TS 38.413) NG-RAN node -> AMF */
|
||||
NGAP_NGAP_PDU_t *encode_ng_path_switch_request(const ngap_path_switch_req_t *msg)
|
||||
{
|
||||
NGAP_NGAP_PDU_t *pdu = calloc_or_fail(1,sizeof(*pdu));
|
||||
|
||||
/* Prepare the NGAP message to encode */
|
||||
pdu->present = NGAP_NGAP_PDU_PR_initiatingMessage;
|
||||
asn1cCalloc(pdu->choice.initiatingMessage, head);
|
||||
head->procedureCode = NGAP_ProcedureCode_id_PathSwitchRequest;
|
||||
head->criticality = NGAP_Criticality_reject;
|
||||
head->value.present = NGAP_InitiatingMessage__value_PR_PathSwitchRequest;
|
||||
NGAP_PathSwitchRequest_t *out = &head->value.choice.PathSwitchRequest;
|
||||
|
||||
// RAN UE NGAP ID (M)
|
||||
asn1cSequenceAdd(out->protocolIEs.list, NGAP_PathSwitchRequestIEs_t, ie1);
|
||||
ie1->id = NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID;
|
||||
ie1->criticality = NGAP_Criticality_reject;
|
||||
ie1->value.present = NGAP_PathSwitchRequestIEs__value_PR_RAN_UE_NGAP_ID;
|
||||
ie1->value.choice.RAN_UE_NGAP_ID = msg->gNB_ue_ngap_id;
|
||||
|
||||
// Source AMF UE NGAP ID (M)
|
||||
asn1cSequenceAdd(out->protocolIEs.list, NGAP_PathSwitchRequestIEs_t, ie2);
|
||||
ie2->id = NGAP_ProtocolIE_ID_id_SourceAMF_UE_NGAP_ID;
|
||||
ie2->criticality = NGAP_Criticality_reject;
|
||||
ie2->value.present = NGAP_PathSwitchRequestIEs__value_PR_AMF_UE_NGAP_ID;
|
||||
asn_uint642INTEGER(&ie2->value.choice.AMF_UE_NGAP_ID, msg->amf_ue_ngap_id);
|
||||
|
||||
// User Location Information (M)
|
||||
{
|
||||
asn1cSequenceAdd(out->protocolIEs.list, NGAP_PathSwitchRequestIEs_t, ie3);
|
||||
ie3->id = NGAP_ProtocolIE_ID_id_UserLocationInformation;
|
||||
ie3->criticality = NGAP_Criticality_ignore;
|
||||
ie3->value.present = NGAP_PathSwitchRequestIEs__value_PR_UserLocationInformation;
|
||||
ie3->value.choice.UserLocationInformation.present = NGAP_UserLocationInformation_PR_userLocationInformationNR;
|
||||
asn1cCalloc(ie3->value.choice.UserLocationInformation.choice.userLocationInformationNR, userinfo_nr_p);
|
||||
|
||||
// NR user location information
|
||||
const target_ran_node_id_t *target = &msg->user_info.target_ng_ran;
|
||||
// CGI (M)
|
||||
MACRO_GNB_ID_TO_CELL_IDENTITY(target->targetgNBId, msg->user_info.nrCellIdentity, &userinfo_nr_p->nR_CGI.nRCellIdentity);
|
||||
MCC_MNC_TO_TBCD(target->plmn_identity.mcc,
|
||||
target->plmn_identity.mnc,
|
||||
target->plmn_identity.mnc_digit_length,
|
||||
&userinfo_nr_p->nR_CGI.pLMNIdentity);
|
||||
// TAI (M)
|
||||
INT24_TO_OCTET_STRING(target->tac, &userinfo_nr_p->tAI.tAC);
|
||||
MCC_MNC_TO_PLMNID(target->plmn_identity.mcc,
|
||||
target->plmn_identity.mnc,
|
||||
target->plmn_identity.mnc_digit_length,
|
||||
&userinfo_nr_p->tAI.pLMNIdentity);
|
||||
}
|
||||
|
||||
// UE Security Capabilities (M)
|
||||
asn1cSequenceAdd(out->protocolIEs.list, NGAP_PathSwitchRequestIEs_t, ie4);
|
||||
ie4->id = NGAP_ProtocolIE_ID_id_UESecurityCapabilities;
|
||||
ie4->criticality = NGAP_Criticality_ignore;
|
||||
ie4->value.present = NGAP_PathSwitchRequestIEs__value_PR_UESecurityCapabilities;
|
||||
encode_ngap_security_capabilities(&ie4->value.choice.UESecurityCapabilities, &msg->security_capabilities);
|
||||
|
||||
// PDU Session Resource to be Switched in Downlink List (M)
|
||||
{
|
||||
asn1cSequenceAdd(out->protocolIEs.list, NGAP_PathSwitchRequestIEs_t, ie5);
|
||||
ie5->id = NGAP_ProtocolIE_ID_id_PDUSessionResourceToBeSwitchedDLList;
|
||||
ie5->criticality = NGAP_Criticality_reject;
|
||||
ie5->value.present = NGAP_PathSwitchRequestIEs__value_PR_PDUSessionResourceToBeSwitchedDLList;
|
||||
|
||||
for (const pdusession_setup_t *pdu = msg->pdusessions_tobeswitched; pdu < msg->pdusessions_tobeswitched + msg->nb_of_pdusessions; pdu++) {
|
||||
asn1cSequenceAdd(ie5->value.choice.PDUSessionResourceToBeSwitchedDLList.list, NGAP_PDUSessionResourceToBeSwitchedDLItem_t, item);
|
||||
item->pDUSessionID = pdu->pdusession_id;
|
||||
/* dLQoSFlowPerTNLInformation */
|
||||
NGAP_PathSwitchRequestTransfer_t transfer = {0};
|
||||
transfer.dL_NGU_UP_TNLInformation.present = NGAP_UPTransportLayerInformation_PR_gTPTunnel;
|
||||
asn1cCalloc(transfer.dL_NGU_UP_TNLInformation.choice.gTPTunnel, tmp);
|
||||
GTP_TEID_TO_ASN1(pdu->n3_outgoing.teid, &tmp->gTP_TEID);
|
||||
tnl_to_bitstring(&tmp->transportLayerAddress, pdu->n3_outgoing.addr);
|
||||
for (int j = 0; j < pdu->nb_of_qos_flow; j++) {
|
||||
asn1cSequenceAdd(transfer.qosFlowAcceptedList.list, NGAP_QosFlowAcceptedItem_t, qosItem);
|
||||
qosItem->qosFlowIdentifier = pdu->associated_qos_flows[j].qfi;
|
||||
}
|
||||
|
||||
void *buf;
|
||||
ssize_t encoded = aper_encode_to_new_buffer(&asn_DEF_NGAP_PathSwitchRequestTransfer, NULL, &transfer, &buf);
|
||||
AssertFatal(encoded > 0, "ASN1 message encoding failed !\n");
|
||||
item->pathSwitchRequestTransfer.buf = buf;
|
||||
item->pathSwitchRequestTransfer.size = encoded;
|
||||
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_PathSwitchRequestTransfer, &transfer);
|
||||
}
|
||||
}
|
||||
return pdu;
|
||||
}
|
||||
|
||||
@@ -20,5 +20,6 @@ NGAP_NGAP_PDU_t *encode_ng_handover_notify(const ngap_handover_notify_t *msg);
|
||||
NGAP_NGAP_PDU_t *encode_ng_ul_ran_status_transfer(const ngap_ran_status_transfer_t *msg);
|
||||
NGAP_NGAP_PDU_t *encode_ng_handover_cancel(const ngap_handover_cancel_t *msg);
|
||||
int decode_ng_handover_cancel_ack(ngap_handover_cancel_ack_t *out, const NGAP_NGAP_PDU_t *pdu);
|
||||
NGAP_NGAP_PDU_t *encode_ng_path_switch_request(const ngap_path_switch_req_t *msg);
|
||||
|
||||
#endif /* NGAP_GNB_MOBILITY_MANAGEMENT_H_ */
|
||||
|
||||
@@ -97,4 +97,7 @@
|
||||
#include "NGAP_DRBStatusDL12.h"
|
||||
#include "NGAP_QosFlowListWithCause.h"
|
||||
#include "NGAP_QosFlowWithCauseItem.h"
|
||||
#include "NGAP_PDUSessionResourceToBeSwitchedDLItem.h"
|
||||
#include "NGAP_QosFlowAcceptedItem.h"
|
||||
#include "NGAP_PathSwitchRequestTransfer.h"
|
||||
#endif // NGAP_MSG_INCLUDES_H
|
||||
|
||||
Reference in New Issue
Block a user