mirror of
https://gitlab.eurecom.fr/oai/openairinterface5g.git
synced 2026-07-13 04:30:28 +00:00
NGAP Path Switch Request Acknowledge: add decode and handler
- Add handler at NGAP for Path Switch Request Acknowledge from AMF
- Add Path Switch Request Acknowledge message type definitions
- Implement decoder for Path Switch Request Acknowledge
(Reference: 3GPP TS 38.413 §9.2.3.9)
- AMF UE NGAP ID (M)
- RAN UE NGAP ID (M)
- Security Context (M)
- PDU Session Resource Switched List (M)
- Allowed NSSAI (M)
- Add required ASN.1 header includes for Path Switch Request Acknowledge 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:
@@ -45,6 +45,8 @@
|
||||
|
||||
#define NR_MAX_NB_PDU_SESSIONS (256)
|
||||
|
||||
#define NR_MAX_NB_ALLOWED_SNSSAI (8) /* Maximum number of allowed S-NSSAI in TS 38.413 */
|
||||
|
||||
#define MAX_DRBS_PER_UE (32) /* Maximum number of Data Radio Bearers per UE
|
||||
* defined for NGAP in TS 38.413 - maxnoofDRBs */
|
||||
#define MAX_PDUS_PER_UE (8) /* Maximum number of PDU Sessions per UE */
|
||||
|
||||
@@ -54,6 +54,7 @@ MESSAGE_DEF(NGAP_UL_RAN_STATUS_TRANSFER, MESSAGE_PRIORITY_MED, ngap_ran_status_t
|
||||
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)
|
||||
MESSAGE_DEF(NGAP_PATH_SWITCH_REQ_ACK, MESSAGE_PRIORITY_MED, ngap_path_switch_req_ack_t, ngap_path_switch_req_ack)
|
||||
|
||||
/* NGAP -> RRC messages */
|
||||
MESSAGE_DEF(NGAP_DOWNLINK_NAS , MESSAGE_PRIORITY_MED, ngap_downlink_nas_t , ngap_downlink_nas )
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
#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_PATH_SWITCH_REQ_ACK(mSGpTR) (mSGpTR)->ittiMsg.ngap_path_switch_req_ack
|
||||
|
||||
#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
|
||||
@@ -686,6 +687,53 @@ typedef struct ngap_path_switch_req_s {
|
||||
pdusession_setup_t pdusessions_tobeswitched[NR_MAX_NB_PDU_SESSIONS];
|
||||
} ngap_path_switch_req_t;
|
||||
|
||||
typedef enum ngap_security_ind_s {
|
||||
NGAP_SECURITY_REQUIRED = 0,
|
||||
NGAP_SECURITY_PREFERRED = 1,
|
||||
NGAP_SECURITY_NOT_NEEDED = 2,
|
||||
} ngap_security_ind_t;
|
||||
|
||||
/* 9.3.1.27 3GPP TS 38.413 */
|
||||
typedef struct security_ind_s {
|
||||
ngap_security_ind_t integrity_protection_ind;
|
||||
ngap_security_ind_t confidentiality_protection_ind;
|
||||
} security_ind_t;
|
||||
|
||||
/* 9.3.4.9 3GPP TS 38.413 */
|
||||
typedef struct path_switch_request_ack_transfer_s {
|
||||
// UL NG-U UP TNL Information (O)
|
||||
gtpu_tunnel_t *n3_incoming;
|
||||
// Security Indication (O)
|
||||
security_ind_t *security_ind;
|
||||
} path_switch_request_ack_transfer_t;
|
||||
|
||||
/* Path Switch Request Acknowledge 9.2.3.9 3GPP TS 38.413
|
||||
* PDU Session Resource Switched Item */
|
||||
typedef struct path_switch_request_ack_pdusession_s {
|
||||
// PDU Session ID (M)
|
||||
int pdusession_id;
|
||||
// Path Switch Request Acknowledge Transfer (M)
|
||||
path_switch_request_ack_transfer_t pathSwitchReqAckTransfer;
|
||||
} path_switch_request_ack_pdusession_t;
|
||||
|
||||
/* Path Switch Request Acknowledge 9.2.3.9 3GPP TS 38.413 */
|
||||
typedef struct ngap_path_switch_req_ack_s {
|
||||
// AMF UE NGAP ID (M)
|
||||
uint64_t amf_ue_ngap_id;
|
||||
// RAN UE NGAP ID (M)
|
||||
uint32_t gNB_ue_ngap_id;
|
||||
// Security Context - Next-Hop Chaining Count (M)
|
||||
uint8_t nh_ncc;
|
||||
// Security Context - Next-Hop NH (M)
|
||||
uint8_t next_security_key[SECURITY_KEY_LENGTH];
|
||||
// List of PDU Session Resource Switched (M)
|
||||
uint16_t nb_of_pdusessions;
|
||||
path_switch_request_ack_pdusession_t pdusessions_switched[NR_MAX_NB_PDU_SESSIONS];
|
||||
// Allowed NSSAI (M)
|
||||
uint8_t nb_allowed_nssais;
|
||||
nssai_t allowed_nssai[NR_MAX_NB_ALLOWED_SNSSAI];
|
||||
} ngap_path_switch_req_ack_t;
|
||||
|
||||
typedef struct ngap_ue_cap_info_ind_s {
|
||||
uint32_t gNB_ue_ngap_id;
|
||||
byte_array_t ue_radio_cap;
|
||||
|
||||
@@ -1092,6 +1092,54 @@ static int ngap_gNB_handle_handover_cancel_ack(sctp_assoc_t assoc_id, uint32_t s
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @brief Handler for NGAP Path Switch Request Acknowledge
|
||||
* AMF -> NG-RAN Node */
|
||||
static int ngap_gNB_handle_ng_path_switch_request_ack(sctp_assoc_t assoc_id, uint32_t stream, NGAP_NGAP_PDU_t *pdu)
|
||||
{
|
||||
NGAP_INFO("Received NG Path Switch Request Acknowledge\n");
|
||||
ngap_gNB_amf_data_t *amf_desc_p = NULL;
|
||||
DevAssert(pdu != NULL);
|
||||
|
||||
if ((amf_desc_p = ngap_gNB_get_AMF(NULL, assoc_id, 0)) == NULL) {
|
||||
NGAP_ERROR("[SCTP %u] Received Path Switch Request "
|
||||
"Acknowledge for non existing AMF context\n", assoc_id);
|
||||
return -1;
|
||||
}
|
||||
MessageDef *message_p = itti_alloc_new_message(TASK_NGAP, 0, NGAP_PATH_SWITCH_REQ_ACK);
|
||||
ngap_path_switch_req_ack_t *msg = &NGAP_PATH_SWITCH_REQ_ACK(message_p);
|
||||
memset(msg, 0, sizeof(*msg));
|
||||
if (decode_ng_path_switch_request_acknowledge(msg, pdu) < 0) {
|
||||
NGAP_ERROR("Failed to decode NG Path Switch Request Acknowledge\n");
|
||||
free_ng_path_switch_req_ack(msg);
|
||||
itti_free(TASK_NGAP, message_p);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ngap_gNB_ue_context_t *ue_desc_p = ngap_get_ue_context(msg->gNB_ue_ngap_id);
|
||||
if (!ue_desc_p) {
|
||||
NGAP_ERROR("[SCTP %u] Received Path Switch Request Acknowledge for non "
|
||||
"existing UE context (gNB_ue_ngap_id %d)\n",
|
||||
assoc_id,
|
||||
msg->gNB_ue_ngap_id);
|
||||
free_ng_path_switch_req_ack(msg);
|
||||
itti_free(TASK_NGAP, message_p);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ue_desc_p->rx_stream = stream;
|
||||
if (ue_desc_p->amf_ue_ngap_id != msg->amf_ue_ngap_id) {
|
||||
NGAP_ERROR("UE context amf_ue_ngap_id is different from that of the message (%ld != %ld)",
|
||||
ue_desc_p->amf_ue_ngap_id,
|
||||
msg->amf_ue_ngap_id);
|
||||
free_ng_path_switch_req_ack(msg);
|
||||
itti_free(TASK_NGAP, message_p);
|
||||
return -1;
|
||||
}
|
||||
|
||||
itti_send_msg_to_task(TASK_RRC_GNB, amf_desc_p->ngap_gNB_instance->instance, message_p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle NGAP Paging message from AMF
|
||||
* @param assoc_id SCTP association ID
|
||||
@@ -1542,7 +1590,7 @@ const ngap_message_decoded_callback ngap_messages_callback[][3] = {
|
||||
{0, 0, 0}, /* OverloadStart */
|
||||
{0, 0, 0}, /* OverloadStop */
|
||||
{ngap_gNB_handle_paging, 0, 0}, /* Paging */
|
||||
{0, 0, 0}, /* PathSwitchRequest */
|
||||
{0, ngap_gNB_handle_ng_path_switch_request_ack, 0}, /* PathSwitchRequest */
|
||||
{ngap_gNB_handle_pdusession_modify_request, 0, 0}, /* PDUSessionResourceModify */
|
||||
{0, 0, 0}, /* PDUSessionResourceModifyIndication */
|
||||
{ngap_gNB_handle_pdusession_release_command, 0, 0}, /* PDUSessionResourceRelease */
|
||||
|
||||
@@ -824,3 +824,92 @@ NGAP_NGAP_PDU_t *encode_ng_path_switch_request(const ngap_path_switch_req_t *msg
|
||||
}
|
||||
return pdu;
|
||||
}
|
||||
|
||||
void free_ng_path_switch_req_ack(ngap_path_switch_req_ack_t *msg)
|
||||
{
|
||||
if (msg == NULL)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < msg->nb_of_pdusessions; i++) {
|
||||
path_switch_request_ack_transfer_t *transfer = &msg->pdusessions_switched[i].pathSwitchReqAckTransfer;
|
||||
|
||||
free(transfer->n3_incoming);
|
||||
transfer->n3_incoming = NULL;
|
||||
|
||||
free(transfer->security_ind);
|
||||
transfer->security_ind = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/** @brief Decode NGAP Path Switch Request Acknowledge (9.2.3.9 3GPP TS 38.413) */
|
||||
int decode_ng_path_switch_request_acknowledge(ngap_path_switch_req_ack_t *msg, NGAP_NGAP_PDU_t *pdu)
|
||||
{
|
||||
DevAssert(pdu != NULL);
|
||||
NGAP_PathSwitchRequestAcknowledgeIEs_t *ie;
|
||||
NGAP_PathSwitchRequestAcknowledge_t *container = &pdu->choice.successfulOutcome->value.choice.PathSwitchRequestAcknowledge;
|
||||
|
||||
// AMF UE NGAP ID (M)
|
||||
NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_PathSwitchRequestAcknowledgeIEs_t, ie, container, NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID, true);
|
||||
asn_INTEGER2ulong(&(ie->value.choice.AMF_UE_NGAP_ID), &msg->amf_ue_ngap_id);
|
||||
|
||||
// RAN UE NGAP ID (M)
|
||||
NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_PathSwitchRequestAcknowledgeIEs_t, ie, container, NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID, true);
|
||||
msg->gNB_ue_ngap_id = ie->value.choice.RAN_UE_NGAP_ID;
|
||||
|
||||
// Security Context (M)
|
||||
NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_PathSwitchRequestAcknowledgeIEs_t, ie, container, NGAP_ProtocolIE_ID_id_SecurityContext, true);
|
||||
msg->nh_ncc = ie->value.choice.SecurityContext.nextHopChainingCount;
|
||||
memcpy(msg->next_security_key, ie->value.choice.SecurityContext.nextHopNH.buf, ie->value.choice.SecurityContext.nextHopNH.size);
|
||||
|
||||
// PDU Session Resource Switched List (M)
|
||||
NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_PathSwitchRequestAcknowledgeIEs_t, ie, container, NGAP_ProtocolIE_ID_id_PDUSessionResourceSwitchedList, true);
|
||||
msg->nb_of_pdusessions = ie->value.choice.PDUSessionResourceSwitchedList.list.count;
|
||||
|
||||
for (int i = 0; i < msg->nb_of_pdusessions; ++i) {
|
||||
NGAP_PDUSessionResourceSwitchedItem_t *item = ie->value.choice.PDUSessionResourceSwitchedList.list.array[i];
|
||||
path_switch_request_ack_pdusession_t *switched = &msg->pdusessions_switched[i];
|
||||
// PDU Session ID (M)
|
||||
switched->pdusession_id = item->pDUSessionID;
|
||||
// Path Switch Request Acknowledge Transfer (M)
|
||||
NGAP_PathSwitchRequestAcknowledgeTransfer_t *psrAckTransfer = NULL;
|
||||
asn_dec_rval_t dec_rval = uper_decode_complete(NULL,
|
||||
&asn_DEF_NGAP_PathSwitchRequestAcknowledgeTransfer,
|
||||
(void **)&psrAckTransfer,
|
||||
item->pathSwitchRequestAcknowledgeTransfer.buf,
|
||||
item->pathSwitchRequestAcknowledgeTransfer.size);
|
||||
if (dec_rval.code != RC_OK) {
|
||||
NGAP_ERROR("Failed to decode Path Switch Request Acknowledge Transfer\n");
|
||||
ASN_STRUCT_FREE(asn_DEF_NGAP_PathSwitchRequestAcknowledgeTransfer, psrAckTransfer);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// UL NG-U UP TNL Information (O)
|
||||
if (psrAckTransfer->uL_NGU_UP_TNLInformation != NULL) {
|
||||
NGAP_UPTransportLayerInformation_t *up_tnl = psrAckTransfer->uL_NGU_UP_TNLInformation;
|
||||
if (up_tnl->present == NGAP_UPTransportLayerInformation_PR_gTPTunnel && up_tnl->choice.gTPTunnel != NULL) {
|
||||
switched->pathSwitchReqAckTransfer.n3_incoming = calloc_or_fail(1, sizeof(*switched->pathSwitchReqAckTransfer.n3_incoming));
|
||||
OCTET_STRING_TO_INT32(&(up_tnl->choice.gTPTunnel->gTP_TEID), switched->pathSwitchReqAckTransfer.n3_incoming->teid);
|
||||
bitstring_to_tnl(&switched->pathSwitchReqAckTransfer.n3_incoming->addr, up_tnl->choice.gTPTunnel->transportLayerAddress);
|
||||
}
|
||||
}
|
||||
|
||||
// Security Indication (O)
|
||||
if (psrAckTransfer->securityIndication != NULL) {
|
||||
switched->pathSwitchReqAckTransfer.security_ind = calloc_or_fail(1, sizeof(*switched->pathSwitchReqAckTransfer.security_ind));
|
||||
switched->pathSwitchReqAckTransfer.security_ind->integrity_protection_ind = psrAckTransfer->securityIndication->integrityProtectionIndication;
|
||||
switched->pathSwitchReqAckTransfer.security_ind->confidentiality_protection_ind = psrAckTransfer->securityIndication->confidentialityProtectionIndication;
|
||||
}
|
||||
|
||||
ASN_STRUCT_FREE(asn_DEF_NGAP_PathSwitchRequestAcknowledgeTransfer, psrAckTransfer);
|
||||
}
|
||||
|
||||
// Allowed NSSAI (M)
|
||||
NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_PathSwitchRequestAcknowledgeIEs_t, ie, container, NGAP_ProtocolIE_ID_id_AllowedNSSAI, true);
|
||||
NGAP_DEBUG("AllowedNSSAI.list.count %d\n", ie->value.choice.AllowedNSSAI.list.count);
|
||||
msg->nb_allowed_nssais = ie->value.choice.AllowedNSSAI.list.count;
|
||||
for (int i = 0; i < msg->nb_allowed_nssais; ++i) {
|
||||
msg->allowed_nssai[i] = decode_ngap_nssai(&ie->value.choice.AllowedNSSAI.list.array[i]->s_NSSAI);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -21,5 +21,7 @@ NGAP_NGAP_PDU_t *encode_ng_ul_ran_status_transfer(const ngap_ran_status_transfer
|
||||
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);
|
||||
int decode_ng_path_switch_request_acknowledge(ngap_path_switch_req_ack_t *msg, NGAP_NGAP_PDU_t *pdu);
|
||||
void free_ng_path_switch_req_ack(ngap_path_switch_req_ack_t *msg);
|
||||
|
||||
#endif /* NGAP_GNB_MOBILITY_MANAGEMENT_H_ */
|
||||
|
||||
@@ -100,4 +100,6 @@
|
||||
#include "NGAP_PDUSessionResourceToBeSwitchedDLItem.h"
|
||||
#include "NGAP_QosFlowAcceptedItem.h"
|
||||
#include "NGAP_PathSwitchRequestTransfer.h"
|
||||
#include "NGAP_PDUSessionResourceSwitchedItem.h"
|
||||
#include "NGAP_PathSwitchRequestAcknowledgeTransfer.h"
|
||||
#endif // NGAP_MSG_INCLUDES_H
|
||||
|
||||
Reference in New Issue
Block a user