Commit b061b576 authored by Guido Casati's avatar Guido Casati

Add Bearer Context Modification Request enc/dec lib

parent f2b80ae3
......@@ -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]);
}
......@@ -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_ */
......@@ -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_ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment