diff --git a/openair2/E1AP/lib/e1ap_bearer_context_management.c b/openair2/E1AP/lib/e1ap_bearer_context_management.c index e58fcbf145..a8f68e70d6 100644 --- a/openair2/E1AP/lib/e1ap_bearer_context_management.c +++ b/openair2/E1AP/lib/e1ap_bearer_context_management.c @@ -179,7 +179,7 @@ static bool eq_pdcp_config(const bearer_context_pdcp_config_t *a, const bearer_c /** @brief Encode SDAP Configuration IE */ static E1AP_SDAP_Configuration_t e1_encode_sdap_config(const bearer_context_sdap_config_t *in) { - E1AP_SDAP_Configuration_t out; + E1AP_SDAP_Configuration_t out = {0}; out.defaultDRB = in->defaultDRB ? E1AP_DefaultDRB_true : E1AP_DefaultDRB_false; out.sDAP_Header_UL = in->sDAP_Header_UL; out.sDAP_Header_DL = in->sDAP_Header_DL; @@ -1050,3 +1050,633 @@ void free_e1ap_context_setup_response(const e1ap_bearer_setup_resp_t *msg) { // Do nothing (no dynamic allocation) } + +/* ============================================ + * E1AP Bearer Context Modification Request + * ============================================ */ + +/** @brief Encode PDU Session Item to modify */ +static E1AP_PDU_Session_Resource_To_Modify_Item_t e1_encode_pdu_session_to_mod_item(const pdu_session_to_mod_t *in) +{ + E1AP_PDU_Session_Resource_To_Modify_Item_t out = {0}; + out.pDU_Session_ID = in->sessionId; + for (const DRB_nGRAN_to_mod_t *j = in->DRBnGRanModList; j < in->DRBnGRanModList + in->numDRB2Modify; j++) { + asn1cCalloc(out.dRB_To_Modify_List_NG_RAN, drb2Mod_List); + asn1cSequenceAdd(drb2Mod_List->list, E1AP_DRB_To_Modify_Item_NG_RAN_t, drb2Mod); + drb2Mod->dRB_ID = j->id; + // PDCP Config (O) + if (j->pdcp_config) { + asn1cCalloc(drb2Mod->pDCP_Configuration, pDCP_Configuration); + *pDCP_Configuration = e1_encode_pdcp_config(j->pdcp_config); + } + // SDAP Config (O) + if (j->sdap_config) { + asn1cCalloc(drb2Mod->sDAP_Configuration, sDAP_Configuration); + *sDAP_Configuration = e1_encode_sdap_config(j->sdap_config); + } + // PDCP SN Status Request (O) + if (j->pdcp_sn_status_requested) { + asn1cCalloc(drb2Mod->pDCP_SN_Status_Request, pDCP_SN_Status_Request); + *pDCP_SN_Status_Request = E1AP_PDCP_SN_Status_Request_requested; + } + // DL UP TNL parameters (O) + if (j->numDlUpParam > 0) { + asn1cCalloc(drb2Mod->dL_UP_Parameters, DL_UP_Param_List); + for (const up_params_t *k = j->DlUpParamList; k < j->DlUpParamList + j->numDlUpParam; k++) { + asn1cSequenceAdd(DL_UP_Param_List->list, E1AP_UP_Parameters_Item_t, DL_UP_Param); + DL_UP_Param->uP_TNL_Information = e1_encode_up_tnl_info(&k->tl_info); + DL_UP_Param->cell_Group_ID = k->cell_group_id; + } + } + // QoS Flows to setup (O) + for (const qos_flow_to_setup_t *k = j->qosFlows; k < j->qosFlows + j->numQosFlow2Setup; k++) { + asn1cCalloc(drb2Mod->flow_Mapping_Information, flow_Mapping_Information); + asn1cSequenceAdd(flow_Mapping_Information->list, E1AP_QoS_Flow_QoS_Parameter_Item_t, ie1_2); + *ie1_2 = e1_encode_qos_flow_to_setup(k); + } + } + return out; +} + +/** @brief Common encoding for the NG-RAN System IE */ +static E1AP_NG_RAN_BearerContextModificationRequest_t *encode_ng_ran_to_mod(E1AP_BearerContextModificationRequestIEs_t *ie) +{ + ie->id = E1AP_ProtocolIE_ID_id_System_BearerContextModificationRequest; + ie->criticality = E1AP_Criticality_reject; + ie->value.present = E1AP_BearerContextModificationRequestIEs__value_PR_System_BearerContextModificationRequest; + E1AP_System_BearerContextModificationRequest_t *reqIE = &ie->value.choice.System_BearerContextModificationRequest; + reqIE->present = E1AP_System_BearerContextModificationRequest_PR_nG_RAN_BearerContextModificationRequest; + E1AP_ProtocolIE_Container_4932P26_t *msgNGRAN_list = calloc_or_fail(1, sizeof(*msgNGRAN_list)); + reqIE->choice.nG_RAN_BearerContextModificationRequest = (struct E1AP_ProtocolIE_Container *)msgNGRAN_list; + asn1cSequenceAdd(msgNGRAN_list->list, E1AP_NG_RAN_BearerContextModificationRequest_t, msgNGRAN); + return msgNGRAN; +} + +/** @brief Encode PDU Session Resource To Setup Modification List item */ +static E1AP_PDU_Session_Resource_To_Setup_Mod_Item_t e1_encode_pdu_session_to_setup_mod_item(const pdu_session_to_setup_t *in) +{ + E1AP_PDU_Session_Resource_To_Setup_Mod_Item_t item = {0}; + // PDU Session ID (M) + item.pDU_Session_ID = in->sessionId; + // PDU Session Type (M) + item.pDU_Session_Type = in->sessionType; + // SNSSAI (M) + item.sNSSAI = e1_encode_snssai(&in->nssai); + // Security indication (M) + item.securityIndication = e1_encode_security_indication(&in->securityIndication); + // NG UL UP Transport Layer Information (M) + item.nG_UL_UP_TNL_Information = e1_encode_up_tnl_info(&in->UP_TL_information); + // DRB to setup + for (const DRB_nGRAN_to_setup_t *j = in->DRBnGRanList; j < in->DRBnGRanList + in->numDRB2Setup; j++) { + asn1cSequenceAdd(item.dRB_To_Setup_Mod_List_NG_RAN.list, E1AP_DRB_To_Setup_Mod_Item_NG_RAN_t, ie1); + // DRB ID (M) + ie1->dRB_ID = j->id; + // SDAP Config (M) + ie1->sDAP_Configuration = e1_encode_sdap_config(&j->sdap_config); + // PDCP Config (M) + ie1->pDCP_Configuration = e1_encode_pdcp_config(&j->pdcp_config); + // Cell Group Information (M) + for (const cell_group_id_t *k = j->cellGroupList; k < j->cellGroupList + j->numCellGroups; k++) { + asn1cSequenceAdd(ie1->cell_Group_Information.list, E1AP_Cell_Group_Information_Item_t, ie1_1); + ie1_1->cell_Group_ID = *k; + } + // QoS Flows Information To Be Setup (M) + for (const qos_flow_to_setup_t *k = j->qosFlows; k < j->qosFlows + j->numQosFlow2Setup; k++) { + asn1cSequenceAdd(ie1->flow_Mapping_Information.list, E1AP_QoS_Flow_QoS_Parameter_Item_t, ie1_2); + *ie1_2 = e1_encode_qos_flow_to_setup(k); + } + } + return item; +} + +/** + * @brief Encodes the E1 Bearer Modification Request message + */ +E1AP_E1AP_PDU_t *encode_E1_bearer_context_mod_request(const e1ap_bearer_mod_req_t *in) +{ + E1AP_E1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); + + // PDU Type + pdu->present = E1AP_E1AP_PDU_PR_initiatingMessage; + asn1cCalloc(pdu->choice.initiatingMessage, msg); + msg->procedureCode = E1AP_ProcedureCode_id_bearerContextModification; + msg->criticality = E1AP_Criticality_reject; + msg->value.present = E1AP_InitiatingMessage__value_PR_BearerContextModificationRequest; + + E1AP_BearerContextModificationRequest_t *out = &msg->value.choice.BearerContextModificationRequest; + + // gNB-CU-CP UE E1AP ID (M) + asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextModificationRequestIEs_t, ie1); + ie1->id = E1AP_ProtocolIE_ID_id_gNB_CU_CP_UE_E1AP_ID; + ie1->criticality = E1AP_Criticality_reject; + ie1->value.present = E1AP_BearerContextModificationRequestIEs__value_PR_GNB_CU_CP_UE_E1AP_ID; + ie1->value.choice.GNB_CU_CP_UE_E1AP_ID = in->gNB_cu_cp_ue_id; + + // gNB-CU-UP UE E1AP ID (M) + asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextModificationRequestIEs_t, ie2); + ie2->id = E1AP_ProtocolIE_ID_id_gNB_CU_UP_UE_E1AP_ID; + ie2->criticality = E1AP_Criticality_reject; + ie2->value.present = E1AP_BearerContextModificationRequestIEs__value_PR_GNB_CU_UP_UE_E1AP_ID; + ie2->value.choice.GNB_CU_UP_UE_E1AP_ID = in->gNB_cu_up_ue_id; + + // Security Information (O) + if (in->secInfo) { + asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextModificationRequestIEs_t, ie3); + ie3->id = E1AP_ProtocolIE_ID_id_SecurityInformation; + ie3->criticality = E1AP_Criticality_reject; + ie3->value.present = E1AP_BearerContextModificationRequestIEs__value_PR_SecurityInformation; + ie3->value.choice.SecurityInformation = e1_encode_security_info(in->secInfo); + } + + // UE DL Aggregate Maximum Bit Rate (O) + if (in->ueDlAggMaxBitRate) { + asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextModificationRequestIEs_t, ie4); + ie4->id = E1AP_ProtocolIE_ID_id_UEDLAggregateMaximumBitRate; + ie4->criticality = E1AP_Criticality_reject; + ie4->value.present = E1AP_BearerContextModificationRequestIEs__value_PR_BitRate; + INT32_TO_OCTET_STRING(*in->ueDlAggMaxBitRate, &ie4->value.choice.BitRate); + } + + // UE DL Maximum Integrity Protected Data Rate (O) + if (in->ueDlMaxIPBitRate) { + asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextModificationRequestIEs_t, ie5); + ie5->id = E1AP_ProtocolIE_ID_id_UEDLMaximumIntegrityProtectedDataRate; + ie5->criticality = E1AP_Criticality_ignore; + ie5->value.present = E1AP_BearerContextModificationRequestIEs__value_PR_BitRate; + INT32_TO_OCTET_STRING(*in->ueDlMaxIPBitRate, &ie5->value.choice.BitRate); + } + + // Bearer Context Status Change (O) + if (in->bearerContextStatus && *in->bearerContextStatus == BEARER_SUSPEND) { + asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextModificationRequestIEs_t, ie6); + ie6->id = E1AP_ProtocolIE_ID_id_BearerContextStatusChange; + ie6->criticality = E1AP_Criticality_reject; + ie6->value.present = E1AP_BearerContextModificationRequestIEs__value_PR_BearerContextStatusChange; + ie6->value.choice.BearerContextStatusChange = E1AP_BearerContextStatusChange_suspend; + } + + // UE Inactivity Timer (O) + if (in->inactivityTimer) { + asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextModificationRequestIEs_t, ie7); + ie7->id = E1AP_ProtocolIE_ID_id_UE_Inactivity_Timer; + ie7->criticality = E1AP_Criticality_ignore; + ie7->value.present = E1AP_BearerContextModificationRequestIEs__value_PR_Inactivity_Timer; + ie7->value.choice.Inactivity_Timer = *in->inactivityTimer; + } + + // Data Discard Required (O) + if (in->dataDiscardRequired) { + asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextModificationRequestIEs_t, ie9); + ie9->id = E1AP_ProtocolIE_ID_id_DataDiscardRequired; + ie9->criticality = E1AP_Criticality_ignore; + ie9->value.present = E1AP_BearerContextModificationRequestIEs__value_PR_DataDiscardRequired; + ie9->value.choice.DataDiscardRequired = in->dataDiscardRequired; + } + + // NG-RAN PDU Session Resource To Setup List (O) + if (in->numPDUSessions) { + asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextModificationRequestIEs_t, setupList); + E1AP_NG_RAN_BearerContextModificationRequest_t *msgNGRAN = encode_ng_ran_to_mod(setupList); + msgNGRAN->id = E1AP_ProtocolIE_ID_id_PDU_Session_Resource_To_Setup_Mod_List; + msgNGRAN->criticality = E1AP_Criticality_reject; + msgNGRAN->value.present = E1AP_NG_RAN_BearerContextModificationRequest__value_PR_PDU_Session_Resource_To_Setup_Mod_List; + E1AP_PDU_Session_Resource_To_Setup_Mod_List_t *pdu2Setup = &msgNGRAN->value.choice.PDU_Session_Resource_To_Setup_Mod_List; + for (int i = 0; i < in->numPDUSessions; i++) { + const pdu_session_to_setup_t *pdu_session = &in->pduSession[i]; + asn1cSequenceAdd(pdu2Setup->list, E1AP_PDU_Session_Resource_To_Setup_Mod_Item_t, item); + *item = e1_encode_pdu_session_to_setup_mod_item(pdu_session); + } + } + + // NG-RAN PDU Session Resource To Modify List (O) + if (in->numPDUSessionsMod) { + asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextModificationRequestIEs_t, modList); + E1AP_NG_RAN_BearerContextModificationRequest_t *msgNGRAN = encode_ng_ran_to_mod(modList); + msgNGRAN->id = E1AP_ProtocolIE_ID_id_PDU_Session_Resource_To_Modify_List; + msgNGRAN->criticality = E1AP_Criticality_reject; + msgNGRAN->value.present = E1AP_NG_RAN_BearerContextModificationRequest__value_PR_PDU_Session_Resource_To_Modify_List; + E1AP_PDU_Session_Resource_To_Modify_List_t *pdu2Setup = &msgNGRAN->value.choice.PDU_Session_Resource_To_Modify_List; + for (const pdu_session_to_mod_t *i = in->pduSessionMod; i < in->pduSessionMod + in->numPDUSessionsMod; i++) { + asn1cSequenceAdd(pdu2Setup->list, E1AP_PDU_Session_Resource_To_Modify_Item_t, ieC3_1); + *ieC3_1 = e1_encode_pdu_session_to_mod_item(i); + } + } + return pdu; +} + +/** @brief Decode PDU Session Item to Setup (Bearer Context Modification Request) */ +static bool e1_decode_pdu_session_to_setup_mod_item(pdu_session_to_setup_t *out, + const E1AP_PDU_Session_Resource_To_Setup_Mod_Item_t *item) +{ + // PDU Session ID (M) + out->sessionId = item->pDU_Session_ID; + // PDU Session Type (M) + out->sessionType = item->pDU_Session_Type; + // S-NSSAI (M) + CHECK_E1AP_DEC(e1_decode_snssai(&out->nssai, &item->sNSSAI)); + // Security Indication (M) + CHECK_E1AP_DEC(e1_decode_security_indication(&out->securityIndication, &item->securityIndication)); + /* NG UL UP Transport Layer Information (M) */ + _E1_EQ_CHECK_INT(item->nG_UL_UP_TNL_Information.present, E1AP_UP_TNL_Information_PR_gTPTunnel); + CHECK_E1AP_DEC(e1_decode_up_tnl_info(&out->UP_TL_information, &item->nG_UL_UP_TNL_Information)); + /* DRB To Setup List ( > 1 item ) */ + const E1AP_DRB_To_Setup_Mod_List_NG_RAN_t *drb2SetupList = &item->dRB_To_Setup_Mod_List_NG_RAN; + _E1_EQ_CHECK_GENERIC(drb2SetupList->list.count > 0, "%d", drb2SetupList->list.count, 0); + out->numDRB2Setup = drb2SetupList->list.count; + _E1_EQ_CHECK_INT(out->numDRB2Setup, 1); // can only handle one DRB per PDU session + for (int j = 0; j < drb2SetupList->list.count; j++) { + DRB_nGRAN_to_setup_t *drb = out->DRBnGRanList + j; + const E1AP_DRB_To_Setup_Mod_Item_NG_RAN_t *drb2Setup = drb2SetupList->list.array[j]; + // DRB ID (M) + drb->id = drb2Setup->dRB_ID; + // SDAP Configuration (M) + CHECK_E1AP_DEC(e1_decode_sdap_config(&drb->sdap_config, &drb2Setup->sDAP_Configuration)); + // PDCP Configuration (M) + CHECK_E1AP_DEC(e1_decode_pdcp_config(&drb->pdcp_config, &drb2Setup->pDCP_Configuration)); + // Cell Group Information (M) + const E1AP_Cell_Group_Information_t *cellGroupList = &drb2Setup->cell_Group_Information; + _E1_EQ_CHECK_GENERIC(cellGroupList->list.count > 0, "%d", cellGroupList->list.count, 0); + drb->numCellGroups = cellGroupList->list.count; + for (int k = 0; k < cellGroupList->list.count; k++) { + const E1AP_Cell_Group_Information_Item_t *cg2Setup = cellGroupList->list.array[k]; + // Cell Group ID + drb->cellGroupList[k] = cg2Setup->cell_Group_ID; + } + // QoS Flows Information To Be Setup (M) + const E1AP_QoS_Flow_QoS_Parameter_List_t *qos2SetupList = &drb2Setup->flow_Mapping_Information; + drb->numQosFlow2Setup = qos2SetupList->list.count; + for (int k = 0; k < qos2SetupList->list.count; k++) { + CHECK_E1AP_DEC(e1_decode_qos_flow_to_setup(drb->qosFlows + k, qos2SetupList->list.array[k])); + } + } + return true; +} + + +/** @brief Decode PDU Session Item to modify (Bearer Context Modification Request) */ +static bool e1_decode_pdu_session_to_mod_item(pdu_session_to_mod_t *out, const E1AP_PDU_Session_Resource_To_Modify_Item_t *in) +{ + // PDU Session ID + out->sessionId = in->pDU_Session_ID; + // DRB to modify list + E1AP_DRB_To_Modify_List_NG_RAN_t *drb2ModList = in->dRB_To_Modify_List_NG_RAN; + out->numDRB2Modify = drb2ModList->list.count; + for (int j = 0; j < drb2ModList->list.count; j++) { + DRB_nGRAN_to_mod_t *drb = out->DRBnGRanModList + j; + // DRB to modify item + E1AP_DRB_To_Modify_Item_NG_RAN_t *drb2Mod = drb2ModList->list.array[j]; + drb->id = drb2Mod->dRB_ID; + // PDCP Config (O) + if (drb2Mod->pDCP_Configuration) { + drb->pdcp_config = malloc_or_fail(sizeof(*drb->pdcp_config)); + CHECK_E1AP_DEC(e1_decode_pdcp_config(drb->pdcp_config, drb2Mod->pDCP_Configuration)); + } + // SDAP Config (O) + if (drb2Mod->sDAP_Configuration) { + drb->sdap_config = malloc_or_fail(sizeof(*drb->sdap_config)); + CHECK_E1AP_DEC(e1_decode_sdap_config(drb->sdap_config, drb2Mod->sDAP_Configuration)); + } + // PDCP SN Status Request (O) + if (drb2Mod->pDCP_SN_Status_Request) { + drb->pdcp_sn_status_requested = true; + } + // DL UP TNL parameters (O) + if (drb2Mod->dL_UP_Parameters) { + E1AP_UP_Parameters_t *dl_up_paramList = drb2Mod->dL_UP_Parameters; + if((drb->numDlUpParam = decode_dl_up_parameters(drb->DlUpParamList, dl_up_paramList)) < 0) { + PRINT_ERROR("Failed to decode DL UP TNL parameters\n"); + return false; + } + } + // QoS Flows Information To Be Setup (O) + E1AP_QoS_Flow_QoS_Parameter_List_t *qos2SetupList = drb2Mod->flow_Mapping_Information; + drb->numQosFlow2Setup = qos2SetupList->list.count; + for (int k = 0; k < qos2SetupList->list.count; k++) { + CHECK_E1AP_DEC(e1_decode_qos_flow_to_setup(drb->qosFlows + k, qos2SetupList->list.array[k])); + } + } + return true; +} + + +/** + * @brief E1 Bearer Modification Request message decoding + */ +bool decode_E1_bearer_context_mod_request(const E1AP_E1AP_PDU_t *pdu, e1ap_bearer_mod_req_t *out) +{ + DevAssert(pdu != NULL); + // Validate message type + _E1_EQ_CHECK_INT(pdu->present, E1AP_E1AP_PDU_PR_initiatingMessage); + const E1AP_InitiatingMessage_t *im = pdu->choice.initiatingMessage; + _E1_EQ_CHECK_LONG(im->procedureCode, E1AP_ProcedureCode_id_bearerContextModification); + _E1_EQ_CHECK_INT(im->value.present, E1AP_InitiatingMessage__value_PR_BearerContextModificationRequest); + + const E1AP_BearerContextModificationRequest_t *in = &im->value.choice.BearerContextModificationRequest; + E1AP_BearerContextModificationRequestIEs_t *ie = NULL; + + // Mandatory IEs + // gNB-CU-CP UE E1AP ID (M) + E1AP_LIB_FIND_IE(E1AP_BearerContextModificationRequestIEs_t, ie, in, E1AP_ProtocolIE_ID_id_gNB_CU_CP_UE_E1AP_ID, true); + // gNB-CU-UP UE E1AP ID (M) + E1AP_LIB_FIND_IE(E1AP_BearerContextModificationRequestIEs_t, ie, in, E1AP_ProtocolIE_ID_id_gNB_CU_UP_UE_E1AP_ID, true); + + // Loop through all IEs and extract + 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: + _E1_EQ_CHECK_INT(ie->value.present, E1AP_BearerContextModificationRequestIEs__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: + _E1_EQ_CHECK_INT(ie->value.present, E1AP_BearerContextModificationRequestIEs__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_SecurityInformation: + out->secInfo = malloc_or_fail(sizeof(*out->secInfo)); + CHECK_E1AP_DEC(e1_decode_security_info(out->secInfo, &ie->value.choice.SecurityInformation)); + break; + + case E1AP_ProtocolIE_ID_id_UEDLAggregateMaximumBitRate: + out->ueDlAggMaxBitRate = malloc_or_fail(sizeof(*out->ueDlAggMaxBitRate)); + OCTET_STRING_TO_UINT32(&ie->value.choice.BitRate, *out->ueDlAggMaxBitRate); + break; + + case E1AP_ProtocolIE_ID_id_UEDLMaximumIntegrityProtectedDataRate: + out->ueDlMaxIPBitRate = malloc_or_fail(sizeof(*out->ueDlMaxIPBitRate)); + OCTET_STRING_TO_UINT32(&ie->value.choice.BitRate, *out->ueDlMaxIPBitRate); + break; + + case E1AP_ProtocolIE_ID_id_BearerContextStatusChange: + _E1_EQ_CHECK_INT(ie->value.present, E1AP_BearerContextModificationRequestIEs__value_PR_BearerContextStatusChange); + if (ie->value.choice.BearerContextStatusChange == E1AP_BearerContextStatusChange_suspend) { + out->bearerContextStatus = malloc_or_fail(sizeof(*out->bearerContextStatus)); + *out->bearerContextStatus = BEARER_SUSPEND; + } + break; + + case E1AP_ProtocolIE_ID_id_UE_Inactivity_Timer: + out->inactivityTimer = malloc_or_fail(sizeof(*out->inactivityTimer)); + *out->inactivityTimer = ie->value.choice.Inactivity_Timer; + break; + + case E1AP_ProtocolIE_ID_id_DataDiscardRequired: + out->dataDiscardRequired = ie->value.choice.DataDiscardRequired; + break; + + case E1AP_ProtocolIE_ID_id_System_BearerContextModificationRequest: { + _E1_EQ_CHECK_INT(ie->value.present, + E1AP_BearerContextModificationRequestIEs__value_PR_System_BearerContextModificationRequest); + E1AP_System_BearerContextModificationRequest_t *modReq = &ie->value.choice.System_BearerContextModificationRequest; + DevAssert(ie->value.choice.System_BearerContextModificationRequest.choice.nG_RAN_BearerContextModificationRequest != NULL); + // System IE can contain either UTRAN or NG-RAN + switch (modReq->present) { + case E1AP_System_BearerContextModificationRequest_PR_NOTHING: + PRINT_ERROR("System Bearer Context Setup Request: no choice present\n"); + break; + case E1AP_System_BearerContextModificationRequest_PR_e_UTRAN_BearerContextModificationRequest: + PRINT_ERROR("UTRAN in E1 Setup Modification Request not supported\n"); + return false; + break; + case E1AP_System_BearerContextModificationRequest_PR_nG_RAN_BearerContextModificationRequest: + // NG-RAN + AssertFatal(modReq->choice.nG_RAN_BearerContextModificationRequest != NULL, + "System_BearerContextSetupRequest->choice.nG_RAN_BearerContextSetupRequest shall not be null"); + E1AP_ProtocolIE_Container_4932P26_t *msgNGRAN_list = + (E1AP_ProtocolIE_Container_4932P26_t *)modReq->choice.nG_RAN_BearerContextModificationRequest; + // loop through all items in the NG-RAN list (to setup, to modify, etc) + for (int i = 0; i < msgNGRAN_list->list.count; i++) { + E1AP_NG_RAN_BearerContextModificationRequest_t *msgNGRAN = msgNGRAN_list->list.array[i]; + switch (msgNGRAN->id) { + case E1AP_ProtocolIE_ID_id_PDU_Session_Resource_To_Setup_Mod_List: + _E1_EQ_CHECK_LONG(msgNGRAN->id, E1AP_ProtocolIE_ID_id_PDU_Session_Resource_To_Setup_Mod_List); + _E1_EQ_CHECK_INT(msgNGRAN->value.present, + E1AP_NG_RAN_BearerContextModificationRequest__value_PR_PDU_Session_Resource_To_Setup_Mod_List); + E1AP_PDU_Session_Resource_To_Setup_Mod_List_t *setupList = + &msgNGRAN->value.choice.PDU_Session_Resource_To_Setup_Mod_List; + // PDU Session Resource To Modify List + out->numPDUSessions = setupList->list.count; + // Loop through all PDU sessions + for (int i = 0; i < setupList->list.count; i++) { + pdu_session_to_setup_t *pdu_session = out->pduSession + i; + E1AP_PDU_Session_Resource_To_Setup_Mod_Item_t *pdu2Setup = setupList->list.array[i]; + CHECK_E1AP_DEC(e1_decode_pdu_session_to_setup_mod_item(pdu_session, pdu2Setup)); + } + break; + case E1AP_ProtocolIE_ID_id_PDU_Session_Resource_To_Modify_List: + /* PDU Session Resource To Modify List (see 9.3.3.11 of TS 38.463) */ + _E1_EQ_CHECK_INT(msgNGRAN->value.present, + E1AP_NG_RAN_BearerContextModificationRequest__value_PR_PDU_Session_Resource_To_Modify_List); + E1AP_PDU_Session_Resource_To_Modify_List_t *modList = &msgNGRAN->value.choice.PDU_Session_Resource_To_Modify_List; + out->numPDUSessionsMod = modList->list.count; + // Loop through all PDU sessions + for (int i = 0; i < modList->list.count; i++) { + CHECK_E1AP_DEC(e1_decode_pdu_session_to_mod_item(out->pduSessionMod + i, modList->list.array[i])); + } + break; + default: + PRINT_ERROR("Unknown msgNGRAN->id in E1 Setup Modification Request\n"); + return false; + break; + } + } + + break; + default: + PRINT_ERROR("System Bearer Context Modification Request: No valid choice present.\n"); + break; + } + + break; + } + + default: + PRINT_ERROR("System Bearer Context Modification Request: this IE is not implemented (or) invalid IE detected\n"); + return false; + break; + } + } + + return true; +} + +/** @brief Deep copy for DRB Item to modify */ +static DRB_nGRAN_to_mod_t cp_drb_to_mod_item(const DRB_nGRAN_to_mod_t *msg) +{ + DRB_nGRAN_to_mod_t cp = {0}; + // shallow copy + cp = *msg; + _E1_CP_OPTIONAL_IE(&cp, msg, sdap_config); + _E1_CP_OPTIONAL_IE(&cp, msg, pdcp_config); + return cp; +} + +/** @brief Deep copy for PDU Session Item to modify */ +static pdu_session_to_mod_t cp_pdu_session_to_mod_item(const pdu_session_to_mod_t *msg) +{ + pdu_session_to_mod_t cp = {0}; + // shallow copy + cp = *msg; + // DRB to setup list + for (int j = 0; j < msg->numDRB2Setup; j++) + cp.DRBnGRanList[j] = cp_drb_to_setup_item(&msg->DRBnGRanList[j]); + // DRB to modify list + for (int j = 0; j < msg->numDRB2Modify; j++) + cp.DRBnGRanModList[j] = cp_drb_to_mod_item(&msg->DRBnGRanModList[j]); + _E1_CP_OPTIONAL_IE(&cp, msg, securityIndication); + _E1_CP_OPTIONAL_IE(&cp, msg, UP_TL_information); + return cp; +} + +/** @brief Deep copy for Bearer Context Modification Request */ +e1ap_bearer_mod_req_t cp_bearer_context_mod_request(const e1ap_bearer_mod_req_t *msg) +{ + e1ap_bearer_mod_req_t cp = {0}; + // Shallow copy + cp = *msg; + // Deep copy for optional fields + _E1_CP_OPTIONAL_IE(&cp, msg, secInfo); + _E1_CP_OPTIONAL_IE(&cp, msg, bearerContextStatus); + _E1_CP_OPTIONAL_IE(&cp, msg, inactivityTimer); + // Deep copy PDU sessions + for (int i = 0; i < msg->numPDUSessions; i++) + cp.pduSession[i] = cp_pdu_session_item(&msg->pduSession[i]); + for (int i = 0; i < msg->numPDUSessionsMod; i++) + cp.pduSessionMod[i] = cp_pdu_session_to_mod_item(&msg->pduSessionMod[i]); + return cp; +} + +/** @brief Equality check for Security Indication IE (3GPP TS 38.463 9.3.1.23) */ +static bool eq_security_ind(security_indication_t *a, security_indication_t *b) +{ + _E1_EQ_CHECK_INT(a->confidentialityProtectionIndication, b->confidentialityProtectionIndication); + _E1_EQ_CHECK_INT(a->integrityProtectionIndication, b->integrityProtectionIndication); + _E1_EQ_CHECK_LONG(a->maxIPrate, b->maxIPrate); + return true; +} + +/** + * @brief Equality check for DRB_nGRAN_to_mod_t + */ +static bool eq_drb_to_mod(const DRB_nGRAN_to_mod_t *a, const DRB_nGRAN_to_mod_t *b) +{ + bool result = true; + _E1_EQ_CHECK_LONG(a->id, b->id); + _E1_EQ_CHECK_INT(a->numQosFlow2Setup, b->numQosFlow2Setup); + for (int i = 0; i < a->numQosFlow2Setup; i++) { + result &= eq_qos_flow(&a->qosFlows[i], &b->qosFlows[i]); + } + _E1_EQ_CHECK_INT(a->numDlUpParam, b->numDlUpParam); + for (int i = 0; i < a->numDlUpParam; i++) { + _E1_EQ_CHECK_INT(a->DlUpParamList[i].cell_group_id, b->DlUpParamList[i].cell_group_id); + eq_up_tl_info(&a->DlUpParamList[i].tl_info, &b->DlUpParamList[i].tl_info); + } + if (a->pdcp_config && b->pdcp_config) + result &= eq_pdcp_config(a->pdcp_config, b->pdcp_config); + if (a->sdap_config && b->sdap_config) + result &= eq_sdap_config(a->sdap_config, b->sdap_config); + return result; +} + +/** @brief Equality check for PDU session item to modify */ +static bool eq_pdu_session_to_mod_item(const pdu_session_to_mod_t *a, const pdu_session_to_mod_t *b) +{ + _E1_EQ_CHECK_LONG(a->sessionId, b->sessionId); + if (a->UP_TL_information && a->UP_TL_information) { + if (!eq_up_tl_info(a->UP_TL_information, b->UP_TL_information)) + return false; + } + _E1_EQ_CHECK_INT(a->numDRB2Setup, b->numDRB2Setup); + for (int i = 0; i < a->numDRB2Setup; i++) { + if (!eq_drb_to_setup(&a->DRBnGRanList[i], &b->DRBnGRanList[i])) + return false; + } + _E1_EQ_CHECK_LONG(a->numDRB2Modify, b->numDRB2Modify); + for (int i = 0; i < a->numDRB2Modify; i++) { + if (!eq_drb_to_mod(&a->DRBnGRanModList[i], &b->DRBnGRanModList[i])) + return false; + } + if (a->securityIndication && b->securityIndication) { + eq_security_ind(a->securityIndication, b->securityIndication); + } + return true; +} + +/** + * @brief E1AP Bearer Modification Request equality check + */ +bool eq_bearer_context_mod_request(const e1ap_bearer_mod_req_t *a, const e1ap_bearer_mod_req_t *b) +{ + // 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->numPDUSessions, b->numPDUSessions); + _E1_EQ_CHECK_INT(a->numPDUSessionsMod, b->numPDUSessionsMod); + // Security Info + _E1_EQ_CHECK_OPTIONAL_PTR(a, b, secInfo); + if (a->secInfo && b->secInfo) { + _E1_EQ_CHECK_LONG(a->secInfo->cipheringAlgorithm, b->secInfo->cipheringAlgorithm); + _E1_EQ_CHECK_LONG(a->secInfo->integrityProtectionAlgorithm, b->secInfo->integrityProtectionAlgorithm); + _E1_EQ_CHECK_STR(a->secInfo->encryptionKey, b->secInfo->encryptionKey); + _E1_EQ_CHECK_STR(a->secInfo->integrityProtectionKey, b->secInfo->integrityProtectionKey); + } + // Bearer Context Status (O) + _E1_EQ_CHECK_OPTIONAL_IE(a, b, bearerContextStatus, _E1_EQ_CHECK_INT); + // Inactivity Timer (O) + _E1_EQ_CHECK_OPTIONAL_PTR(a, b, inactivityTimer); + if (a->inactivityTimer && b->inactivityTimer) + _E1_EQ_CHECK_INT(*a->inactivityTimer, *b->inactivityTimer); + // Activity Notification Level (O) + // PDU Sessions + if (a->numPDUSessions != b->numPDUSessions) + return false; + for (int i = 0; i < a->numPDUSessions; i++) { + if (!eq_pdu_session_item(&a->pduSession[i], &b->pduSession[i])) + return false; + } + // Modified PDU Sessions + if (a->numPDUSessionsMod != b->numPDUSessionsMod) + return false; + for (int i = 0; i < a->numPDUSessionsMod; i++) { + if (!eq_pdu_session_to_mod_item(&a->pduSessionMod[i], &b->pduSessionMod[i])) + return false; + } + return true; +} + +/* Free DRB to modify item */ +static void free_drb_to_mod_item(const DRB_nGRAN_to_mod_t *msg) +{ + free(msg->pdcp_config); + free(msg->sdap_config); +} + +/* Free PDU Session to modify item */ +void free_pdu_session_to_mod_item(const pdu_session_to_mod_t *msg) +{ + free(msg->securityIndication); + free(msg->UP_TL_information); + for (int i = 0; i < msg->numDRB2Modify; i++) + free_drb_to_mod_item(&msg->DRBnGRanModList[i]); + for (int i = 0; i < msg->numDRB2Setup; i++) + free_drb_to_setup_item(&msg->DRBnGRanList[i]); +} + +/** + * @brief E1AP Bearer Context Modification Request memory management + */ +void free_e1ap_context_mod_request(const e1ap_bearer_mod_req_t *msg) +{ + free(msg->secInfo); + free(msg->ueDlAggMaxBitRate); + free(msg->ueDlMaxIPBitRate); + free(msg->bearerContextStatus); + free(msg->inactivityTimer); + for (int i = 0; i < msg->numPDUSessions; i++) + free_pdu_session_to_setup_item(&msg->pduSession[i]); + for (int i = 0; i < msg->numPDUSessionsMod; i++) + free_pdu_session_to_mod_item(&msg->pduSessionMod[i]); +} diff --git a/openair2/E1AP/lib/e1ap_bearer_context_management.h b/openair2/E1AP/lib/e1ap_bearer_context_management.h index 95e4cb0e15..132c1857e1 100644 --- a/openair2/E1AP/lib/e1ap_bearer_context_management.h +++ b/openair2/E1AP/lib/e1ap_bearer_context_management.h @@ -40,4 +40,10 @@ void free_e1ap_context_setup_response(const e1ap_bearer_setup_resp_t *msg); e1ap_bearer_setup_resp_t cp_bearer_context_setup_response(const e1ap_bearer_setup_resp_t *msg); bool eq_bearer_context_setup_response(const e1ap_bearer_setup_resp_t *a, const e1ap_bearer_setup_resp_t *b); +struct E1AP_E1AP_PDU *encode_E1_bearer_context_mod_request(const e1ap_bearer_mod_req_t *msg); +bool decode_E1_bearer_context_mod_request(const struct E1AP_E1AP_PDU *pdu, e1ap_bearer_mod_req_t *out); +void free_e1ap_context_mod_request(const e1ap_bearer_mod_req_t *msg); +e1ap_bearer_mod_req_t cp_bearer_context_mod_request(const e1ap_bearer_mod_req_t *msg); +bool eq_bearer_context_mod_request(const e1ap_bearer_mod_req_t *a, const e1ap_bearer_mod_req_t *b); + #endif /* E1AP_BEARER_CONTEXT_MANAGEMENT_H_ */ diff --git a/openair2/E1AP/lib/e1ap_lib_includes.h b/openair2/E1AP/lib/e1ap_lib_includes.h index 785fd9d09c..46d09f5aa9 100644 --- a/openair2/E1AP/lib/e1ap_lib_includes.h +++ b/openair2/E1AP/lib/e1ap_lib_includes.h @@ -67,5 +67,11 @@ #include "E1AP_Transport-UP-Layer-Addresses-Info-To-Remove-Item.h" #include "E1AP_GTPTLAs.h" #include "E1AP_GTPTLA-Item.h" +// E1 Bearer Context Modification Request +#include "E1AP_PDU-Session-Resource-To-Modify-Item.h" +#include "E1AP_DRB-To-Modify-List-NG-RAN.h" +#include "E1AP_DRB-To-Modify-Item-NG-RAN.h" +#include "E1AP_PDU-Session-Resource-To-Setup-Mod-Item.h" +#include "E1AP_DRB-To-Setup-Mod-Item-NG-RAN.h" #endif /* E1AP_LIB_INCLUDES_H_ */