|
|
|
@@ -782,6 +782,26 @@ bool eq_bearer_context_setup_request(const e1ap_bearer_setup_req_t *a, const e1a
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Decode DRB Failed Item. Applies to both E1AP_DRB_Failed_To_Modify_Item_NG_RAN_t
|
|
|
|
|
* and E1AP_DRB_Failed_Item_NG_RAN_t */
|
|
|
|
|
static void decode_drb_failed_item(DRB_nGRAN_failed_t *out, const E1AP_DRB_Failed_Item_NG_RAN_t *in)
|
|
|
|
|
{
|
|
|
|
|
// DRB ID (M)
|
|
|
|
|
out->id = in->dRB_ID;
|
|
|
|
|
// Cause (M)
|
|
|
|
|
out->cause = e1_decode_cause_ie(&in->cause);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Encode DRB Failed Item. Applies to both E1AP_DRB_Failed_To_Modify_Item_NG_RAN_t
|
|
|
|
|
* and E1AP_DRB_Failed_Item_NG_RAN_t */
|
|
|
|
|
static void encode_drb_failed_item(E1AP_DRB_Failed_Item_NG_RAN_t *out, const DRB_nGRAN_failed_t *in)
|
|
|
|
|
{
|
|
|
|
|
// DRB ID (M)
|
|
|
|
|
out->dRB_ID = in->id;
|
|
|
|
|
// Cause (M)
|
|
|
|
|
out->cause = e1_encode_cause_ie(&in->cause);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ======================================
|
|
|
|
|
* E1AP Bearer Context Setup Response
|
|
|
|
|
* ====================================== */
|
|
|
|
@@ -1047,8 +1067,8 @@ bool eq_bearer_context_setup_response(const e1ap_bearer_setup_resp_t *a, const e
|
|
|
|
|
const DRB_nGRAN_failed_t *drbf_a = &ps_a->DRBnGRanFailedList[j];
|
|
|
|
|
const DRB_nGRAN_failed_t *drbf_b = &ps_b->DRBnGRanFailedList[j];
|
|
|
|
|
_E1_EQ_CHECK_LONG(drbf_a->id, drbf_b->id);
|
|
|
|
|
_E1_EQ_CHECK_LONG(drbf_a->cause.type, drbf_b->cause.type);
|
|
|
|
|
_E1_EQ_CHECK_LONG(drbf_a->cause.value, drbf_b->cause.value);
|
|
|
|
|
_E1_EQ_CHECK_INT(drbf_a->cause.type, drbf_b->cause.type);
|
|
|
|
|
_E1_EQ_CHECK_INT(drbf_a->cause.value, drbf_b->cause.value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
@@ -1507,7 +1527,7 @@ bool decode_E1_bearer_context_mod_request(const E1AP_E1AP_PDU_t *pdu, e1ap_beare
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
PRINT_ERROR("System Bearer Context Modification Request: this IE is not implemented (or) invalid IE detected\n");
|
|
|
|
|
PRINT_ERROR("%s: handle for this IE %ld is not implemented (or) invalid IE detected\n", __func__, ie->id);
|
|
|
|
|
return false;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
@@ -1693,3 +1713,425 @@ void free_e1ap_context_mod_request(const e1ap_bearer_mod_req_t *msg)
|
|
|
|
|
for (int i = 0; i < msg->numPDUSessionsMod; i++)
|
|
|
|
|
free_pdu_session_to_mod_item(&msg->pduSessionMod[i]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ============================================
|
|
|
|
|
* E1AP Bearer Context Modification Response
|
|
|
|
|
* ============================================ */
|
|
|
|
|
|
|
|
|
|
/** Encode QoS Flow Item (9.3.1.12 3GPP TS 38.463) */
|
|
|
|
|
static void encode_qos_flow_failed_item(E1AP_QoS_Flow_Failed_Item_t *out, const qos_flow_failed_t *in)
|
|
|
|
|
{
|
|
|
|
|
// QFI (M)
|
|
|
|
|
out->qoS_Flow_Identifier = in->qfi;
|
|
|
|
|
// Cause (M)
|
|
|
|
|
out->cause = e1_encode_cause_ie(&in->cause);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Bearer Context Modification Response encoding (9.2.2.5 3GPP TS 38.463)
|
|
|
|
|
* gNB-CU-UP → gNB-CU-CP
|
|
|
|
|
*/
|
|
|
|
|
struct E1AP_E1AP_PDU *encode_E1_bearer_context_mod_response(const e1ap_bearer_modif_resp_t *msg)
|
|
|
|
|
{
|
|
|
|
|
E1AP_E1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu));
|
|
|
|
|
|
|
|
|
|
pdu->present = E1AP_E1AP_PDU_PR_successfulOutcome;
|
|
|
|
|
asn1cCalloc(pdu->choice.successfulOutcome, type);
|
|
|
|
|
type->procedureCode = E1AP_ProcedureCode_id_bearerContextModification;
|
|
|
|
|
type->criticality = E1AP_Criticality_reject;
|
|
|
|
|
type->value.present = E1AP_SuccessfulOutcome__value_PR_BearerContextModificationResponse;
|
|
|
|
|
E1AP_BearerContextModificationResponse_t *out = &pdu->choice.successfulOutcome->value.choice.BearerContextModificationResponse;
|
|
|
|
|
// gNB-CU-CP UE E1AP ID (M)
|
|
|
|
|
asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextModificationResponseIEs_t, ie1);
|
|
|
|
|
ie1->id = E1AP_ProtocolIE_ID_id_gNB_CU_CP_UE_E1AP_ID;
|
|
|
|
|
ie1->criticality = E1AP_Criticality_reject;
|
|
|
|
|
ie1->value.present = E1AP_BearerContextModificationResponseIEs__value_PR_GNB_CU_CP_UE_E1AP_ID;
|
|
|
|
|
ie1->value.choice.GNB_CU_CP_UE_E1AP_ID = msg->gNB_cu_cp_ue_id;
|
|
|
|
|
// gNB-CU-UP UE E1AP ID (M)
|
|
|
|
|
asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextModificationResponseIEs_t, ie2);
|
|
|
|
|
ie2->id = E1AP_ProtocolIE_ID_id_gNB_CU_UP_UE_E1AP_ID;
|
|
|
|
|
ie2->criticality = E1AP_Criticality_reject;
|
|
|
|
|
ie2->value.present = E1AP_BearerContextModificationResponseIEs__value_PR_GNB_CU_UP_UE_E1AP_ID;
|
|
|
|
|
ie2->value.choice.GNB_CU_UP_UE_E1AP_ID = msg->gNB_cu_up_ue_id;
|
|
|
|
|
// NG-RAN PDU Session Resource Modified List (O)
|
|
|
|
|
asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextModificationResponseIEs_t, ie3);
|
|
|
|
|
ie3->id = E1AP_ProtocolIE_ID_id_System_BearerContextModificationResponse;
|
|
|
|
|
ie3->criticality = E1AP_Criticality_ignore;
|
|
|
|
|
// CHOICE System (O)
|
|
|
|
|
ie3->value.present = E1AP_BearerContextModificationResponseIEs__value_PR_System_BearerContextModificationResponse;
|
|
|
|
|
E1AP_System_BearerContextModificationResponse_t *sys = &ie3->value.choice.System_BearerContextModificationResponse;
|
|
|
|
|
// NG-RAN
|
|
|
|
|
E1AP_ProtocolIE_Container_4932P29_t *ngran = calloc_or_fail(1, sizeof(*ngran));
|
|
|
|
|
sys->present = E1AP_System_BearerContextModificationResponse_PR_nG_RAN_BearerContextModificationResponse;
|
|
|
|
|
sys->choice.nG_RAN_BearerContextModificationResponse = (struct E1AP_ProtocolIE_Container *)ngran;
|
|
|
|
|
asn1cSequenceAdd(ngran->list, E1AP_NG_RAN_BearerContextModificationResponse_t, list);
|
|
|
|
|
// PDU Session Resource Modified List (O)
|
|
|
|
|
list->id = E1AP_ProtocolIE_ID_id_PDU_Session_Resource_Modified_List;
|
|
|
|
|
list->criticality = E1AP_Criticality_reject;
|
|
|
|
|
list->value.present = E1AP_NG_RAN_BearerContextModificationResponse__value_PR_PDU_Session_Resource_Modified_List;
|
|
|
|
|
E1AP_PDU_Session_Resource_Modified_List_t *pdu_mod_l = &list->value.choice.PDU_Session_Resource_Modified_List;
|
|
|
|
|
for (int i = 0; i < msg->numPDUSessionsMod; ++i) {
|
|
|
|
|
// PDU Session Resource Modified Item (1..maxnoofPDUSessionResource)
|
|
|
|
|
const pdu_session_modif_t *pdu = &msg->pduSessionMod[i];
|
|
|
|
|
asn1cSequenceAdd(pdu_mod_l->list, E1AP_PDU_Session_Resource_Modified_Item_t, iePdu);
|
|
|
|
|
// PDU Session ID (M)
|
|
|
|
|
iePdu->pDU_Session_ID = pdu->id;
|
|
|
|
|
// Security Result (O)
|
|
|
|
|
if (pdu->confidentialityProtectionIndication || pdu->integrityProtectionIndication) {
|
|
|
|
|
iePdu->securityResult = calloc_or_fail(1, sizeof(*iePdu->securityResult));
|
|
|
|
|
if (pdu->confidentialityProtectionIndication)
|
|
|
|
|
iePdu->securityResult->confidentialityProtectionResult = *pdu->confidentialityProtectionIndication;
|
|
|
|
|
if (pdu->integrityProtectionIndication)
|
|
|
|
|
iePdu->securityResult->integrityProtectionResult = *pdu->integrityProtectionIndication;
|
|
|
|
|
}
|
|
|
|
|
// NG DL UP Transport Layer Information (O)
|
|
|
|
|
if (pdu->ng_DL_UP_TL_info) {
|
|
|
|
|
iePdu->nG_DL_UP_TNL_Information = calloc_or_fail(1, sizeof(*iePdu->nG_DL_UP_TNL_Information));
|
|
|
|
|
*iePdu->nG_DL_UP_TNL_Information = e1_encode_up_tnl_info(pdu->ng_DL_UP_TL_info);
|
|
|
|
|
}
|
|
|
|
|
// DRB Modified List (O)
|
|
|
|
|
if (pdu->numDRBModified > 0) {
|
|
|
|
|
iePdu->dRB_Modified_List_NG_RAN = calloc_or_fail(1, sizeof(*iePdu->dRB_Modified_List_NG_RAN));
|
|
|
|
|
E1AP_DRB_Modified_List_NG_RAN_t *drb_mod_l = iePdu->dRB_Modified_List_NG_RAN;
|
|
|
|
|
for (int j = 0; j < pdu->numDRBModified; ++j) {
|
|
|
|
|
const DRB_nGRAN_modified_t *drb = &pdu->DRBnGRanModList[j];
|
|
|
|
|
asn1cSequenceAdd(drb_mod_l->list, E1AP_DRB_Modified_Item_NG_RAN_t, drb_mod);
|
|
|
|
|
// DRB ID (M)
|
|
|
|
|
drb_mod->dRB_ID = drb->id;
|
|
|
|
|
// Flow Setup List (O)
|
|
|
|
|
if (drb->numQosFlowSetup)
|
|
|
|
|
drb_mod->flow_Setup_List = calloc_or_fail(1, sizeof(*drb_mod->flow_Setup_List));
|
|
|
|
|
for (int q = 0; q < drb->numQosFlowSetup; ++q) {
|
|
|
|
|
asn1cSequenceAdd(drb_mod->flow_Setup_List->list, E1AP_QoS_Flow_Item_t, qos_mod);
|
|
|
|
|
qos_mod->qoS_Flow_Identifier = drb->qosFlows[q].qfi;
|
|
|
|
|
}
|
|
|
|
|
// Flow Failed List (O)
|
|
|
|
|
if (drb->numQosFlowFailed)
|
|
|
|
|
drb_mod->flow_Failed_List = calloc_or_fail(1, sizeof(*drb_mod->flow_Failed_List));
|
|
|
|
|
for (int q = 0; q < drb->numQosFlowFailed; ++q) {
|
|
|
|
|
asn1cSequenceAdd(drb_mod->flow_Failed_List->list, E1AP_QoS_Flow_Failed_Item_t, fail);
|
|
|
|
|
encode_qos_flow_failed_item(fail, &drb->qosFlowsFailed[q]);
|
|
|
|
|
}
|
|
|
|
|
// UL UP Parameters (O)
|
|
|
|
|
if (drb->numUpParam)
|
|
|
|
|
drb_mod->uL_UP_Transport_Parameters = calloc_or_fail(1, sizeof(*drb_mod->uL_UP_Transport_Parameters));
|
|
|
|
|
for (const up_params_t *k = drb->ul_UP_Params; k < drb->ul_UP_Params + drb->numUpParam; k++) {
|
|
|
|
|
asn1cSequenceAdd(drb_mod->uL_UP_Transport_Parameters->list, E1AP_UP_Parameters_Item_t, up);
|
|
|
|
|
up->uP_TNL_Information = e1_encode_up_tnl_info(&k->tl_info);
|
|
|
|
|
up->cell_Group_ID = k->cell_group_id;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// DRB Failed To Modify List (O)
|
|
|
|
|
if (pdu->numDRBFailedToMod > 0) {
|
|
|
|
|
iePdu->dRB_Failed_To_Modify_List_NG_RAN = calloc_or_fail(1, sizeof(*iePdu->dRB_Failed_To_Modify_List_NG_RAN));
|
|
|
|
|
E1AP_DRB_Failed_To_Modify_List_NG_RAN_t *ngran = iePdu->dRB_Failed_To_Modify_List_NG_RAN;
|
|
|
|
|
for (int j = 0; j < pdu->numDRBFailedToMod; ++j) {
|
|
|
|
|
const DRB_nGRAN_failed_t *drb = &pdu->DRBnGRanFailedModList[j];
|
|
|
|
|
asn1cSequenceAdd(ngran->list, E1AP_DRB_Failed_To_Modify_Item_NG_RAN_t, fail_to_mod);
|
|
|
|
|
encode_drb_failed_item((E1AP_DRB_Failed_Item_NG_RAN_t *)fail_to_mod, drb);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// DRB Setup List (O)
|
|
|
|
|
if (pdu->numDRBSetup > 0) {
|
|
|
|
|
iePdu->dRB_Setup_List_NG_RAN = calloc_or_fail(1, sizeof(*iePdu->dRB_Setup_List_NG_RAN));
|
|
|
|
|
E1AP_DRB_Setup_List_NG_RAN_t *drb_setup = iePdu->dRB_Setup_List_NG_RAN;
|
|
|
|
|
for (int j = 0; j < pdu->numDRBModified; ++j) {
|
|
|
|
|
const DRB_nGRAN_setup_t *drb = &pdu->DRBnGRanSetupList[j];
|
|
|
|
|
asn1cSequenceAdd(drb_setup->list, E1AP_DRB_Setup_Item_NG_RAN_t, item);
|
|
|
|
|
// DRB ID (M)
|
|
|
|
|
item->dRB_ID = drb->id;
|
|
|
|
|
// UL UP Parameters (M)
|
|
|
|
|
for (const up_params_t *k = drb->UpParamList; k < drb->UpParamList + drb->numUpParam; k++) {
|
|
|
|
|
asn1cSequenceAdd(item->uL_UP_Transport_Parameters.list, E1AP_UP_Parameters_Item_t, up);
|
|
|
|
|
up->uP_TNL_Information = e1_encode_up_tnl_info(&k->tl_info);
|
|
|
|
|
up->cell_Group_ID = drb->UpParamList->cell_group_id;
|
|
|
|
|
}
|
|
|
|
|
// Flow Setup List (M)
|
|
|
|
|
for (int q = 0; q < drb->numQosFlowSetup; ++q) {
|
|
|
|
|
asn1cSequenceAdd(item->flow_Setup_List.list, E1AP_QoS_Flow_Item_t, qos);
|
|
|
|
|
qos->qoS_Flow_Identifier = drb->qosFlows[q].qfi;
|
|
|
|
|
}
|
|
|
|
|
// Flow Failed List (O)
|
|
|
|
|
if (drb->numQosFlowFailed)
|
|
|
|
|
item->flow_Failed_List = calloc_or_fail(1, sizeof(*item->flow_Failed_List));
|
|
|
|
|
for (int q = 0; q < drb->numQosFlowFailed; ++q) {
|
|
|
|
|
asn1cSequenceAdd(item->flow_Failed_List->list, E1AP_QoS_Flow_Failed_Item_t, fail);
|
|
|
|
|
encode_qos_flow_failed_item(fail, &drb->qosFlowsFailed[q]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// DRB Failed List (O)
|
|
|
|
|
if (pdu->numDRBFailed) {
|
|
|
|
|
iePdu->dRB_Failed_List_NG_RAN = calloc_or_fail(1, sizeof(*iePdu->dRB_Failed_List_NG_RAN));
|
|
|
|
|
E1AP_DRB_Failed_List_NG_RAN_t *ngran = iePdu->dRB_Failed_List_NG_RAN;
|
|
|
|
|
for (int j = 0; j < pdu->numDRBFailed; ++j) {
|
|
|
|
|
const DRB_nGRAN_failed_t *drb = &pdu->DRBnGRanFailedList[j];
|
|
|
|
|
asn1cSequenceAdd(ngran->list, E1AP_DRB_Failed_Item_NG_RAN_t, fail);
|
|
|
|
|
encode_drb_failed_item(fail, drb);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return pdu;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Decode QoS Flow Item (9.3.1.12 3GPP TS 38.463) */
|
|
|
|
|
static qos_flow_failed_t decode_qos_flow_failed_item(const E1AP_QoS_Flow_Failed_Item_t *in)
|
|
|
|
|
{
|
|
|
|
|
qos_flow_failed_t out = {0};
|
|
|
|
|
// QFI (M)
|
|
|
|
|
out.qfi = in->qoS_Flow_Identifier;
|
|
|
|
|
// Cause (M)
|
|
|
|
|
out.cause = e1_decode_cause_ie(&in->cause);
|
|
|
|
|
return out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Bearer Context Modification Response decoding (9.2.2.5 3GPP TS 38.463)
|
|
|
|
|
* gNB-CU-UP → gNB-CU-CP
|
|
|
|
|
*/
|
|
|
|
|
bool decode_E1_bearer_context_mod_response(e1ap_bearer_modif_resp_t *out, const E1AP_E1AP_PDU_t *pdu)
|
|
|
|
|
{
|
|
|
|
|
DevAssert(pdu != NULL);
|
|
|
|
|
_E1_EQ_CHECK_INT(pdu->present, E1AP_E1AP_PDU_PR_successfulOutcome);
|
|
|
|
|
E1AP_SuccessfulOutcome_t *type = pdu->choice.successfulOutcome;
|
|
|
|
|
_E1_EQ_CHECK_LONG(type->procedureCode, E1AP_ProcedureCode_id_bearerContextModification);
|
|
|
|
|
_E1_EQ_CHECK_INT(type->value.present, E1AP_SuccessfulOutcome__value_PR_BearerContextModificationResponse);
|
|
|
|
|
const E1AP_BearerContextModificationResponse_t *in = &type->value.choice.BearerContextModificationResponse;
|
|
|
|
|
// Check mandatory IEs first
|
|
|
|
|
E1AP_BearerContextModificationResponseIEs_t *ie;
|
|
|
|
|
E1AP_LIB_FIND_IE(E1AP_BearerContextModificationResponseIEs_t, ie, in, E1AP_ProtocolIE_ID_id_gNB_CU_CP_UE_E1AP_ID, true);
|
|
|
|
|
E1AP_LIB_FIND_IE(E1AP_BearerContextModificationResponseIEs_t, ie, in, E1AP_ProtocolIE_ID_id_gNB_CU_UP_UE_E1AP_ID, true);
|
|
|
|
|
// Process all IEs
|
|
|
|
|
for (int i = 0; i < in->protocolIEs.list.count; ++i) {
|
|
|
|
|
ie = in->protocolIEs.list.array[i];
|
|
|
|
|
switch (ie->id) {
|
|
|
|
|
case E1AP_ProtocolIE_ID_id_gNB_CU_CP_UE_E1AP_ID:
|
|
|
|
|
// gNB-CU-CP UE E1AP ID (M)
|
|
|
|
|
_E1_EQ_CHECK_INT(ie->value.present, E1AP_BearerContextModificationResponseIEs__value_PR_GNB_CU_CP_UE_E1AP_ID);
|
|
|
|
|
out->gNB_cu_cp_ue_id = ie->value.choice.GNB_CU_CP_UE_E1AP_ID;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case E1AP_ProtocolIE_ID_id_gNB_CU_UP_UE_E1AP_ID:
|
|
|
|
|
// gNB-CU-UP UE E1AP ID (M)
|
|
|
|
|
_E1_EQ_CHECK_INT(ie->value.present, E1AP_BearerContextModificationResponseIEs__value_PR_GNB_CU_UP_UE_E1AP_ID);
|
|
|
|
|
out->gNB_cu_up_ue_id = ie->value.choice.GNB_CU_UP_UE_E1AP_ID;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case E1AP_ProtocolIE_ID_id_System_BearerContextModificationResponse:
|
|
|
|
|
// CHOICE System (O)
|
|
|
|
|
_E1_EQ_CHECK_INT(ie->value.present, E1AP_BearerContextModificationResponseIEs__value_PR_System_BearerContextModificationResponse);
|
|
|
|
|
// NG-RAN System
|
|
|
|
|
E1AP_System_BearerContextModificationResponse_t *system = &ie->value.choice.System_BearerContextModificationResponse;
|
|
|
|
|
_E1_EQ_CHECK_INT(system->present, E1AP_System_BearerContextModificationResponse_PR_nG_RAN_BearerContextModificationResponse);
|
|
|
|
|
// NG-RAN List
|
|
|
|
|
E1AP_ProtocolIE_Container_4932P29_t *msgNGRAN_list = (E1AP_ProtocolIE_Container_4932P29_t *)system->choice.nG_RAN_BearerContextModificationResponse;
|
|
|
|
|
_E1_EQ_CHECK_INT(msgNGRAN_list->list.count, 1);
|
|
|
|
|
E1AP_NG_RAN_BearerContextModificationResponse_t *msgNGRAN = msgNGRAN_list->list.array[0];
|
|
|
|
|
_E1_EQ_CHECK_LONG(msgNGRAN->id, E1AP_ProtocolIE_ID_id_PDU_Session_Resource_Modified_List);
|
|
|
|
|
_E1_EQ_CHECK_INT(msgNGRAN->value.present, E1AP_NG_RAN_BearerContextModificationResponse__value_PR_PDU_Session_Resource_Modified_List);
|
|
|
|
|
// PDU Session Resource Modified list (O)
|
|
|
|
|
E1AP_PDU_Session_Resource_Modified_List_t *list = &msgNGRAN->value.choice.PDU_Session_Resource_Modified_List;
|
|
|
|
|
out->numPDUSessionsMod = list->list.count;
|
|
|
|
|
for (int i = 0; i < list->list.count; i++) {
|
|
|
|
|
// PDU Session Resource Modified item (1..maxnoofPDUSessionResource)
|
|
|
|
|
pdu_session_modif_t *pduModified = &out->pduSessionMod[i];
|
|
|
|
|
E1AP_PDU_Session_Resource_Modified_Item_t *pduIE = list->list.array[i];
|
|
|
|
|
// PDU Session ID (M)
|
|
|
|
|
pduModified->id = pduIE->pDU_Session_ID;
|
|
|
|
|
// NG DL UP Transport Layer Information (O)
|
|
|
|
|
if (pduIE->nG_DL_UP_TNL_Information) {
|
|
|
|
|
pduModified->ng_DL_UP_TL_info = malloc_or_fail(sizeof(*pduModified->ng_DL_UP_TL_info));
|
|
|
|
|
e1_decode_up_tnl_info(pduModified->ng_DL_UP_TL_info, pduIE->nG_DL_UP_TNL_Information);
|
|
|
|
|
}
|
|
|
|
|
// Security Result (O)
|
|
|
|
|
if (pduIE->securityResult) {
|
|
|
|
|
pduModified->confidentialityProtectionIndication = malloc_or_fail(sizeof(*pduModified->confidentialityProtectionIndication));
|
|
|
|
|
*pduModified->confidentialityProtectionIndication = pduIE->securityResult->confidentialityProtectionResult;
|
|
|
|
|
pduModified->integrityProtectionIndication = malloc_or_fail(sizeof(*pduModified->integrityProtectionIndication));
|
|
|
|
|
*pduModified->integrityProtectionIndication = pduIE->securityResult->integrityProtectionResult;
|
|
|
|
|
}
|
|
|
|
|
// DRB Setup list
|
|
|
|
|
if (pduIE->dRB_Setup_List_NG_RAN) {
|
|
|
|
|
pduModified->numDRBSetup = pduIE->dRB_Setup_List_NG_RAN->list.count;
|
|
|
|
|
for (int j = 0; j < pduIE->dRB_Setup_List_NG_RAN->list.count; j++) {
|
|
|
|
|
// DRB Setup item
|
|
|
|
|
DRB_nGRAN_setup_t *drbMod = &pduModified->DRBnGRanSetupList[j];
|
|
|
|
|
E1AP_DRB_Setup_Item_NG_RAN_t *drbIE = pduIE->dRB_Setup_List_NG_RAN->list.array[j];
|
|
|
|
|
drbMod->id = drbIE->dRB_ID;
|
|
|
|
|
// UL UP Parameters (M)
|
|
|
|
|
if (drbIE->uL_UP_Transport_Parameters.list.count) {
|
|
|
|
|
drbMod->numUpParam = decode_dl_up_parameters(drbMod->UpParamList, &drbIE->uL_UP_Transport_Parameters);
|
|
|
|
|
}
|
|
|
|
|
// Flow Setup List (O)
|
|
|
|
|
if (drbIE->flow_Failed_List) {
|
|
|
|
|
drbMod->numQosFlowFailed = drbIE->flow_Failed_List->list.count;
|
|
|
|
|
for (int i = 0; i < drbMod->numQosFlowSetup; i++) {
|
|
|
|
|
drbMod->qosFlowsFailed[i] = decode_qos_flow_failed_item(drbIE->flow_Failed_List->list.array[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// Flow Setup List (M)
|
|
|
|
|
if (drbIE->flow_Setup_List.list.count) {
|
|
|
|
|
drbMod->numQosFlowSetup = drbIE->flow_Setup_List.list.count;
|
|
|
|
|
for (int i = 0; i < drbMod->numQosFlowSetup; i++)
|
|
|
|
|
drbMod->qosFlows[i].qfi = drbIE->flow_Setup_List.list.array[i]->qoS_Flow_Identifier;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// DRB Failed list
|
|
|
|
|
if (pduIE->dRB_Failed_List_NG_RAN) {
|
|
|
|
|
pduModified->numDRBFailed = pduIE->dRB_Failed_List_NG_RAN->list.count;
|
|
|
|
|
for (int j = 0; j < pduIE->dRB_Failed_List_NG_RAN->list.count; j++) {
|
|
|
|
|
decode_drb_failed_item(&pduModified->DRBnGRanFailedList[j], pduIE->dRB_Failed_List_NG_RAN->list.array[j]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// DRB Modified list (0..1)
|
|
|
|
|
if (pduIE->dRB_Modified_List_NG_RAN) {
|
|
|
|
|
pduModified->numDRBModified = pduIE->dRB_Modified_List_NG_RAN->list.count;
|
|
|
|
|
for (int j = 0; j < pduIE->dRB_Modified_List_NG_RAN->list.count; j++) {
|
|
|
|
|
// DRB Modified item
|
|
|
|
|
DRB_nGRAN_modified_t *drbMod = &pduModified->DRBnGRanModList[j];
|
|
|
|
|
E1AP_DRB_Modified_Item_NG_RAN_t *drbIE = pduIE->dRB_Modified_List_NG_RAN->list.array[j];
|
|
|
|
|
// DRB ID (M)
|
|
|
|
|
drbMod->id = drbIE->dRB_ID;
|
|
|
|
|
// UL UP Parameters (O)
|
|
|
|
|
if (drbIE->uL_UP_Transport_Parameters) {
|
|
|
|
|
drbMod->numUpParam = decode_dl_up_parameters(drbMod->ul_UP_Params, drbIE->uL_UP_Transport_Parameters);
|
|
|
|
|
}
|
|
|
|
|
// Flow Setup List (O)
|
|
|
|
|
if (drbIE->flow_Setup_List) {
|
|
|
|
|
drbMod->numQosFlowSetup = drbIE->flow_Setup_List->list.count;
|
|
|
|
|
for (int i = 0; i < drbMod->numQosFlowSetup; i++)
|
|
|
|
|
drbMod->qosFlows[i].qfi = drbIE->flow_Setup_List->list.array[i]->qoS_Flow_Identifier;
|
|
|
|
|
}
|
|
|
|
|
// Flow Failed List (O)
|
|
|
|
|
if (drbIE->flow_Failed_List) {
|
|
|
|
|
drbMod->numQosFlowFailed = drbIE->flow_Failed_List->list.count;
|
|
|
|
|
for (int i = 0; i < drbMod->numQosFlowFailed; i++) {
|
|
|
|
|
drbMod->qosFlowsFailed[i] = decode_qos_flow_failed_item(drbIE->flow_Failed_List->list.array[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// DRB Failed to Mod list
|
|
|
|
|
if (pduIE->dRB_Failed_To_Modify_List_NG_RAN) {
|
|
|
|
|
pduModified->numDRBFailedToMod = pduIE->dRB_Failed_To_Modify_List_NG_RAN->list.count;
|
|
|
|
|
for (int j = 0; j < pduIE->dRB_Failed_To_Modify_List_NG_RAN->list.count; j++) {
|
|
|
|
|
decode_drb_failed_item(&pduModified->DRBnGRanFailedModList[j],
|
|
|
|
|
(E1AP_DRB_Failed_Item_NG_RAN_t *)pduIE->dRB_Failed_To_Modify_List_NG_RAN->list.array[j]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** @brief Deep copy for PDU Session Modified Item */
|
|
|
|
|
static pdu_session_modif_t cp_pdu_session_mod_item(const pdu_session_modif_t *msg)
|
|
|
|
|
{
|
|
|
|
|
pdu_session_modif_t cp = {0};
|
|
|
|
|
// shallow copy
|
|
|
|
|
cp = *msg;
|
|
|
|
|
// Optional IE
|
|
|
|
|
_E1_CP_OPTIONAL_IE(&cp, msg, integrityProtectionIndication);
|
|
|
|
|
_E1_CP_OPTIONAL_IE(&cp, msg, confidentialityProtectionIndication);
|
|
|
|
|
_E1_CP_OPTIONAL_IE(&cp, msg, ng_DL_UP_TL_info);
|
|
|
|
|
return cp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** @brief Deep copy for Bearer Context Modification Response */
|
|
|
|
|
e1ap_bearer_modif_resp_t cp_bearer_context_mod_response(const e1ap_bearer_modif_resp_t *msg)
|
|
|
|
|
{
|
|
|
|
|
e1ap_bearer_modif_resp_t cp = {0};
|
|
|
|
|
// Shallow copy
|
|
|
|
|
cp = *msg;
|
|
|
|
|
// Deep copy PDU sessions modified items
|
|
|
|
|
for (int i = 0; i < msg->numPDUSessionsMod; i++)
|
|
|
|
|
cp.pduSessionMod[i] = cp_pdu_session_mod_item(&msg->pduSessionMod[i]);
|
|
|
|
|
return cp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief E1AP Bearer Modification Response equality check
|
|
|
|
|
*/
|
|
|
|
|
bool eq_bearer_context_mod_response(const e1ap_bearer_modif_resp_t *a, const e1ap_bearer_modif_resp_t *b)
|
|
|
|
|
{
|
|
|
|
|
if (!a || !b) return false; // Null-check both inputs
|
|
|
|
|
|
|
|
|
|
// Basic members
|
|
|
|
|
_E1_EQ_CHECK_INT(a->gNB_cu_cp_ue_id, b->gNB_cu_cp_ue_id);
|
|
|
|
|
_E1_EQ_CHECK_INT(a->gNB_cu_up_ue_id, b->gNB_cu_up_ue_id);
|
|
|
|
|
_E1_EQ_CHECK_INT(a->numPDUSessionsMod, b->numPDUSessionsMod);
|
|
|
|
|
|
|
|
|
|
// PDU Session Modified List
|
|
|
|
|
for (int i = 0; i < a->numPDUSessionsMod; i++) {
|
|
|
|
|
const pdu_session_modif_t *pduA = &a->pduSessionMod[i];
|
|
|
|
|
const pdu_session_modif_t *pduB = &b->pduSessionMod[i];
|
|
|
|
|
|
|
|
|
|
_E1_EQ_CHECK_LONG(pduA->id, pduB->id);
|
|
|
|
|
_E1_EQ_CHECK_OPTIONAL_IE(pduA, pduB, confidentialityProtectionIndication, _E1_EQ_CHECK_INT);
|
|
|
|
|
_E1_EQ_CHECK_OPTIONAL_IE(pduA, pduB, integrityProtectionIndication, _E1_EQ_CHECK_INT);
|
|
|
|
|
|
|
|
|
|
_E1_EQ_CHECK_OPTIONAL_PTR(pduA, pduB, ng_DL_UP_TL_info);
|
|
|
|
|
if (pduA->ng_DL_UP_TL_info && pduB->ng_DL_UP_TL_info)
|
|
|
|
|
eq_up_tl_info(pduA->ng_DL_UP_TL_info, pduB->ng_DL_UP_TL_info);
|
|
|
|
|
|
|
|
|
|
// DRB Modified List
|
|
|
|
|
_E1_EQ_CHECK_INT(pduA->numDRBModified, pduB->numDRBModified);
|
|
|
|
|
for (int j = 0; j < pduA->numDRBModified; j++) {
|
|
|
|
|
const DRB_nGRAN_modified_t *drbModA = &pduA->DRBnGRanModList[j];
|
|
|
|
|
const DRB_nGRAN_modified_t *drbModB = &pduB->DRBnGRanModList[j];
|
|
|
|
|
_E1_EQ_CHECK_LONG(drbModA->id, drbModB->id);
|
|
|
|
|
_E1_EQ_CHECK_INT(drbModA->numQosFlowSetup, drbModB->numQosFlowSetup);
|
|
|
|
|
for (int j = 0; j < drbModA->numQosFlowSetup; j++) {
|
|
|
|
|
_E1_EQ_CHECK_LONG(drbModA->qosFlows[j].qfi, drbModB->qosFlows[j].qfi);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// DRB Failed to Modify List
|
|
|
|
|
_E1_EQ_CHECK_INT(pduA->numDRBFailedToMod, pduB->numDRBFailedToMod);
|
|
|
|
|
for (int j = 0; j < pduA->numDRBFailedToMod; j++) {
|
|
|
|
|
_E1_EQ_CHECK_LONG(pduA->DRBnGRanFailedModList[j].id, pduB->DRBnGRanFailedModList[j].id);
|
|
|
|
|
_E1_EQ_CHECK_INT(pduA->DRBnGRanFailedModList[j].cause.value, pduB->DRBnGRanFailedModList[j].cause.value);
|
|
|
|
|
_E1_EQ_CHECK_INT(pduA->DRBnGRanFailedModList[j].cause.type, pduB->DRBnGRanFailedModList[j].cause.type);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// DRB Setup List
|
|
|
|
|
_E1_EQ_CHECK_INT(pduA->numDRBSetup, pduB->numDRBSetup);
|
|
|
|
|
for (int j = 0; j < pduA->numDRBSetup; j++) {
|
|
|
|
|
const DRB_nGRAN_setup_t *drbSetupA = &pduA->DRBnGRanSetupList[j];
|
|
|
|
|
const DRB_nGRAN_setup_t *drbSetupB = &pduB->DRBnGRanSetupList[j];
|
|
|
|
|
|
|
|
|
|
_E1_EQ_CHECK_LONG(drbSetupA->id, drbSetupB->id);
|
|
|
|
|
_E1_EQ_CHECK_INT(drbSetupA->numQosFlowSetup, drbSetupB->numQosFlowSetup);
|
|
|
|
|
for (int j = 0; j < drbSetupA->numQosFlowSetup; j++) {
|
|
|
|
|
_E1_EQ_CHECK_LONG(drbSetupA->qosFlows[j].qfi, drbSetupB->qosFlows[j].qfi);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// DRB Failed to Setup List
|
|
|
|
|
_E1_EQ_CHECK_INT(pduA->numDRBFailed, pduB->numDRBFailed);
|
|
|
|
|
for (int j = 0; j < pduA->numDRBFailed; j++) {
|
|
|
|
|
_E1_EQ_CHECK_LONG(pduA->DRBnGRanFailedList[j].id, pduB->DRBnGRanFailedList[j].id);
|
|
|
|
|
_E1_EQ_CHECK_INT(pduA->DRBnGRanFailedList[j].cause.value, pduB->DRBnGRanFailedList[j].cause.value);
|
|
|
|
|
_E1_EQ_CHECK_INT(pduA->DRBnGRanFailedList[j].cause.type, pduB->DRBnGRanFailedList[j].cause.type);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief E1AP Bearer Context Modification Response memory management
|
|
|
|
|
*/
|
|
|
|
|
void free_e1ap_context_mod_response(const e1ap_bearer_modif_resp_t *msg)
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0; i < msg->numPDUSessionsMod; i++) {
|
|
|
|
|
free(msg->pduSessionMod[i].confidentialityProtectionIndication);
|
|
|
|
|
free(msg->pduSessionMod[i].integrityProtectionIndication);
|
|
|
|
|
free(msg->pduSessionMod[i].ng_DL_UP_TL_info);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|