Merge remote-tracking branch 'origin/e1-bearer-mod-encdec-tests' into integration_2025_w17 (!3261)
Add Bearer Context Modification Request/Response enc/dec lib and adopt in stack This MR is introducing the Bearer Context Modification Response enc/dec library with relative unit test, and it is also adopting it in the stack. Also: - Refactor Security Information IE decoding function - Adopt Bearer Context Modification Request lib in stack (introduced in !3219 (merged))
This commit is contained in:
@@ -344,6 +344,7 @@ typedef enum qos_flow_mapping_indication_e {
|
||||
QF_BOTH
|
||||
} qos_flow_mapping_indication_t;
|
||||
|
||||
// 9.3.1.12 QoS Flow List
|
||||
typedef struct qos_flow_list_s {
|
||||
long qfi; // qos flow identifier
|
||||
qos_flow_mapping_indication_t *indication;
|
||||
@@ -517,6 +518,12 @@ typedef struct e1ap_bearer_release_cplt_s {
|
||||
uint32_t gNB_cu_up_ue_id;
|
||||
} e1ap_bearer_release_cplt_t;
|
||||
|
||||
// 9.3.1.45 Flow Failed List
|
||||
typedef struct qos_flow_failed_s {
|
||||
long qfi;
|
||||
e1ap_cause_t cause;
|
||||
} qos_flow_failed_t;
|
||||
|
||||
typedef struct DRB_nGRAN_setup_s {
|
||||
// DRB ID (M)
|
||||
long id;
|
||||
@@ -525,6 +532,9 @@ typedef struct DRB_nGRAN_setup_s {
|
||||
// Flow Setup List (M)
|
||||
int numQosFlowSetup;
|
||||
qos_flow_list_t qosFlows[E1AP_MAX_NUM_QOS_FLOWS];
|
||||
// Flow Failed List (O)
|
||||
int numQosFlowFailed;
|
||||
qos_flow_failed_t qosFlowsFailed[E1AP_MAX_NUM_QOS_FLOWS];
|
||||
} DRB_nGRAN_setup_t;
|
||||
|
||||
/* DRB Modified Item */
|
||||
@@ -537,6 +547,9 @@ typedef struct DRB_nGRAN_modified_s {
|
||||
// Flow Setup List (O)
|
||||
int numQosFlowSetup;
|
||||
qos_flow_list_t qosFlows[E1AP_MAX_NUM_QOS_FLOWS];
|
||||
// Flow Failed List (O)
|
||||
int numQosFlowFailed;
|
||||
qos_flow_failed_t qosFlowsFailed[E1AP_MAX_NUM_QOS_FLOWS];
|
||||
// Old QoS Flow List (O)
|
||||
int numOldQosFlow;
|
||||
qos_flow_list_t oldQosFlows[E1AP_MAX_NUM_QOS_FLOWS];
|
||||
@@ -569,9 +582,15 @@ typedef struct pdu_session_modif_s {
|
||||
// DRB Modified List (O)
|
||||
int numDRBModified;
|
||||
DRB_nGRAN_modified_t DRBnGRanModList[E1AP_MAX_NUM_DRBS];
|
||||
// DRB Failed to Modify List (O)
|
||||
int numDRBFailedToMod;
|
||||
DRB_nGRAN_failed_t DRBnGRanFailedModList[E1AP_MAX_NUM_DRBS];
|
||||
// DRB Setup List (O)
|
||||
int numDRBSetup;
|
||||
DRB_nGRAN_setup_t DRBnGRanSetupList[E1AP_MAX_NUM_DRBS];
|
||||
// DRB Failed List (O)
|
||||
int numDRBFailed;
|
||||
DRB_nGRAN_failed_t DRBnGRanFailedList[E1AP_MAX_NUM_DRBS];
|
||||
} pdu_session_modif_t;
|
||||
|
||||
typedef struct e1ap_bearer_setup_resp_s {
|
||||
|
||||
+17
-354
@@ -427,168 +427,16 @@ int e1apCUCP_handle_BEARER_CONTEXT_SETUP_FAILURE(sctp_assoc_t assoc_id, e1ap_upc
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
BEARER CONTEXT MODIFICATION REQUEST
|
||||
*/
|
||||
|
||||
static int fill_BEARER_CONTEXT_MODIFICATION_REQUEST(e1ap_bearer_mod_req_t *const bearerCxt, E1AP_E1AP_PDU_t *pdu)
|
||||
{
|
||||
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 = &pdu->choice.initiatingMessage->value.choice.BearerContextModificationRequest;
|
||||
/* mandatory */
|
||||
/* c1. gNB-CU-CP UE E1AP ID */
|
||||
asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextModificationRequestIEs_t, ieC1);
|
||||
ieC1->id = E1AP_ProtocolIE_ID_id_gNB_CU_CP_UE_E1AP_ID;
|
||||
ieC1->criticality = E1AP_Criticality_reject;
|
||||
ieC1->value.present = E1AP_BearerContextModificationRequestIEs__value_PR_GNB_CU_CP_UE_E1AP_ID;
|
||||
ieC1->value.choice.GNB_CU_CP_UE_E1AP_ID = bearerCxt->gNB_cu_cp_ue_id;
|
||||
/* mandatory */
|
||||
/* c2. gNB-CU-UP UE E1AP ID */
|
||||
asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextModificationRequestIEs_t, ieC2);
|
||||
ieC2->id = E1AP_ProtocolIE_ID_id_gNB_CU_UP_UE_E1AP_ID;
|
||||
ieC2->criticality = E1AP_Criticality_reject;
|
||||
ieC2->value.present = E1AP_BearerContextModificationRequestIEs__value_PR_GNB_CU_UP_UE_E1AP_ID;
|
||||
ieC2->value.choice.GNB_CU_UP_UE_E1AP_ID = bearerCxt->gNB_cu_up_ue_id;
|
||||
/* optional */
|
||||
/* Security Information */
|
||||
if (bearerCxt->secInfo) {
|
||||
asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextModificationRequestIEs_t, ie);
|
||||
ie->id = E1AP_ProtocolIE_ID_id_SecurityInformation;
|
||||
ie->criticality = E1AP_Criticality_reject;
|
||||
ie->value.present = E1AP_BearerContextModificationRequestIEs__value_PR_SecurityInformation;
|
||||
E1AP_SecurityAlgorithm_t *securityAlgorithm = &ie->value.choice.SecurityInformation.securityAlgorithm;
|
||||
E1AP_UPSecuritykey_t *uPSecuritykey = &ie->value.choice.SecurityInformation.uPSecuritykey;
|
||||
securityAlgorithm->cipheringAlgorithm = bearerCxt->secInfo->cipheringAlgorithm;
|
||||
OCTET_STRING_fromBuf(&uPSecuritykey->encryptionKey, bearerCxt->secInfo->encryptionKey, E1AP_SECURITY_KEY_SIZE);
|
||||
asn1cCallocOne(securityAlgorithm->integrityProtectionAlgorithm, bearerCxt->secInfo->integrityProtectionAlgorithm);
|
||||
asn1cCalloc(uPSecuritykey->integrityProtectionKey, protKey);
|
||||
OCTET_STRING_fromBuf(protKey, bearerCxt->secInfo->integrityProtectionKey, E1AP_SECURITY_KEY_SIZE);
|
||||
}
|
||||
/* optional */
|
||||
/* c3. E1AP_ProtocolIE_ID_id_System_BearerContextModificationRequest */
|
||||
asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextModificationRequestIEs_t, ieC3);
|
||||
ieC3->id = E1AP_ProtocolIE_ID_id_System_BearerContextModificationRequest;
|
||||
ieC3->criticality = E1AP_Criticality_reject;
|
||||
ieC3->value.present = E1AP_BearerContextModificationRequestIEs__value_PR_System_BearerContextModificationRequest;
|
||||
ieC3->value.choice.System_BearerContextModificationRequest.present = E1AP_System_BearerContextModificationRequest_PR_nG_RAN_BearerContextModificationRequest;
|
||||
E1AP_ProtocolIE_Container_4932P26_t *msgNGRAN_list = calloc(1, sizeof(E1AP_ProtocolIE_Container_4932P26_t));
|
||||
ieC3->value.choice.System_BearerContextModificationRequest.choice.nG_RAN_BearerContextModificationRequest = (struct E1AP_ProtocolIE_Container *) msgNGRAN_list;
|
||||
asn1cSequenceAdd(msgNGRAN_list->list, E1AP_NG_RAN_BearerContextModificationRequest_t, msgNGRAN);
|
||||
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 (pdu_session_to_mod_t *i = bearerCxt->pduSessionMod; i < bearerCxt->pduSessionMod + bearerCxt->numPDUSessionsMod; i++) {
|
||||
asn1cSequenceAdd(pdu2Setup->list, E1AP_PDU_Session_Resource_To_Modify_Item_t, ieC3_1);
|
||||
ieC3_1->pDU_Session_ID = i->sessionId;
|
||||
for (DRB_nGRAN_to_mod_t *j = i->DRBnGRanModList; j < i->DRBnGRanModList + i->numDRB2Modify; j++) {
|
||||
asn1cCalloc(ieC3_1->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;
|
||||
asn1cCalloc(drb2Mod->pDCP_Configuration, pDCP_Configuration);
|
||||
if (j->pdcp_config && j->pdcp_config->pDCP_Reestablishment) {
|
||||
asn1cCallocOne(pDCP_Configuration->pDCP_Reestablishment, E1AP_PDCP_Reestablishment_true);
|
||||
}
|
||||
if (j->numDlUpParam > 0) {
|
||||
asn1cCalloc(drb2Mod->dL_UP_Parameters, DL_UP_Param_List);
|
||||
for (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.present = E1AP_UP_TNL_Information_PR_gTPTunnel;
|
||||
asn1cCalloc(DL_UP_Param->uP_TNL_Information.choice.gTPTunnel, gTPTunnel);
|
||||
TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(k->tl_info.tlAddress, &gTPTunnel->transportLayerAddress);
|
||||
INT32_TO_OCTET_STRING(k->tl_info.teId, &gTPTunnel->gTP_TEID);
|
||||
|
||||
DL_UP_Param->cell_Group_ID = k->cell_group_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* c4. E1AP_ProtocolIE_ID_id_BearerContextStatusChange */
|
||||
if (bearerCxt->bearerContextStatus && *bearerCxt->bearerContextStatus == BEARER_SUSPEND) {
|
||||
asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextModificationRequestIEs_t, ieC4);
|
||||
ieC4->id = E1AP_ProtocolIE_ID_id_BearerContextStatusChange;
|
||||
ieC4->criticality = E1AP_Criticality_reject;
|
||||
ieC4->value.present = E1AP_BearerContextModificationRequestIEs__value_PR_BearerContextStatusChange;
|
||||
/* Bearer Context Status Change */
|
||||
ieC4->value.choice.BearerContextStatusChange = E1AP_BearerContextStatusChange_suspend;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void e1apCUCP_send_BEARER_CONTEXT_MODIFICATION_REQUEST(sctp_assoc_t assoc_id, e1ap_bearer_mod_req_t *const bearerCxt)
|
||||
{
|
||||
E1AP_E1AP_PDU_t pdu = {0};
|
||||
fill_BEARER_CONTEXT_MODIFICATION_REQUEST(bearerCxt, &pdu);
|
||||
e1ap_encode_send(CPtype, assoc_id, &pdu, 0, __func__);
|
||||
}
|
||||
|
||||
static void fill_BEARER_CONTEXT_MODIFICATION_RESPONSE(const e1ap_bearer_modif_resp_t *resp, E1AP_E1AP_PDU_t *pdu)
|
||||
{
|
||||
pdu->present = E1AP_E1AP_PDU_PR_successfulOutcome;
|
||||
asn1cCalloc(pdu->choice.successfulOutcome, msg);
|
||||
msg->procedureCode = E1AP_ProcedureCode_id_bearerContextModification;
|
||||
msg->criticality = E1AP_Criticality_reject;
|
||||
msg->value.present = E1AP_SuccessfulOutcome__value_PR_BearerContextModificationResponse;
|
||||
E1AP_BearerContextModificationResponse_t *out = &pdu->choice.successfulOutcome->value.choice.BearerContextModificationResponse;
|
||||
|
||||
/* mandatory */
|
||||
/* c1. gNB-CU-CP UE E1AP ID */
|
||||
asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextModificationResponseIEs_t, ieCuCpId);
|
||||
ieCuCpId->id = E1AP_ProtocolIE_ID_id_gNB_CU_CP_UE_E1AP_ID;
|
||||
ieCuCpId->criticality = E1AP_Criticality_reject;
|
||||
ieCuCpId->value.present = E1AP_BearerContextModificationResponseIEs__value_PR_GNB_CU_CP_UE_E1AP_ID;
|
||||
ieCuCpId->value.choice.GNB_CU_CP_UE_E1AP_ID = resp->gNB_cu_cp_ue_id;
|
||||
|
||||
/* mandatory */
|
||||
/* c2. gNB-CU-UP UE E1AP ID */
|
||||
asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextModificationResponseIEs_t, ieCuUpId);
|
||||
ieCuUpId->id = E1AP_ProtocolIE_ID_id_gNB_CU_UP_UE_E1AP_ID;
|
||||
ieCuUpId->criticality = E1AP_Criticality_reject;
|
||||
ieCuUpId->value.present = E1AP_BearerContextModificationResponseIEs__value_PR_GNB_CU_UP_UE_E1AP_ID;
|
||||
ieCuUpId->value.choice.GNB_CU_UP_UE_E1AP_ID = resp->gNB_cu_up_ue_id;
|
||||
|
||||
/* optional */
|
||||
/* PDU sessions that have been modified */
|
||||
asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextModificationResponseIEs_t, ieSys);
|
||||
ieSys->id = E1AP_ProtocolIE_ID_id_System_BearerContextModificationResponse;
|
||||
ieSys->criticality = E1AP_Criticality_ignore;
|
||||
ieSys->value.present = E1AP_BearerContextModificationResponseIEs__value_PR_System_BearerContextModificationResponse;
|
||||
|
||||
E1AP_System_BearerContextModificationResponse_t *sys = &ieSys->value.choice.System_BearerContextModificationResponse;
|
||||
E1AP_ProtocolIE_Container_4932P29_t *piel = calloc(1, sizeof(*piel));
|
||||
sys->present = E1AP_System_BearerContextModificationResponse_PR_nG_RAN_BearerContextModificationResponse;
|
||||
sys->choice.nG_RAN_BearerContextModificationResponse = (struct E1AP_ProtocolIE_Container *)piel;
|
||||
asn1cSequenceAdd(piel->list, E1AP_NG_RAN_BearerContextModificationResponse_t, ngran_bcmr);
|
||||
ngran_bcmr->id = E1AP_ProtocolIE_ID_id_PDU_Session_Resource_Modified_List;
|
||||
ngran_bcmr->criticality = E1AP_Criticality_reject;
|
||||
ngran_bcmr->value.present = E1AP_NG_RAN_BearerContextModificationResponse__value_PR_PDU_Session_Resource_Modified_List;
|
||||
E1AP_PDU_Session_Resource_Modified_List_t *pdu_mod_l = &ngran_bcmr->value.choice.PDU_Session_Resource_Modified_List;
|
||||
for (int i = 0; i < resp->numPDUSessionsMod; ++i) {
|
||||
const pdu_session_modif_t *pdu = &resp->pduSessionMod[i];
|
||||
asn1cSequenceAdd(pdu_mod_l->list, E1AP_PDU_Session_Resource_Modified_Item_t, iePdu);
|
||||
iePdu->pDU_Session_ID = pdu->id;
|
||||
if (pdu->numDRBModified > 0) {
|
||||
iePdu->dRB_Modified_List_NG_RAN = calloc(1, sizeof(*iePdu->dRB_Modified_List_NG_RAN));
|
||||
AssertFatal(iePdu->dRB_Modified_List_NG_RAN != NULL, "out of memory\n");
|
||||
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_mod->dRB_ID = drb->id;
|
||||
}
|
||||
}
|
||||
}
|
||||
E1AP_E1AP_PDU_t *pdu = encode_E1_bearer_context_mod_request(bearerCxt);
|
||||
e1ap_encode_send(CPtype, assoc_id, pdu, 0, __func__);
|
||||
}
|
||||
|
||||
static int e1apCUUP_send_BEARER_CONTEXT_MODIFICATION_RESPONSE(sctp_assoc_t assoc_id, const e1ap_bearer_modif_resp_t *resp)
|
||||
{
|
||||
E1AP_E1AP_PDU_t pdu = {0};
|
||||
fill_BEARER_CONTEXT_MODIFICATION_RESPONSE(resp, &pdu);
|
||||
return e1ap_encode_send(UPtype, assoc_id, &pdu, 0, __func__);
|
||||
E1AP_E1AP_PDU_t *pdu = encode_E1_bearer_context_mod_response(resp);
|
||||
return e1ap_encode_send(UPtype, assoc_id, pdu, 0, __func__);
|
||||
}
|
||||
|
||||
int e1apCUUP_send_BEARER_CONTEXT_MODIFICATION_FAILURE(instance_t instance)
|
||||
@@ -597,121 +445,6 @@ int e1apCUUP_send_BEARER_CONTEXT_MODIFICATION_FAILURE(instance_t instance)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Process E1AP PDU and extract Bearer Context Modification Request
|
||||
*/
|
||||
static void extract_BEARER_CONTEXT_MODIFICATION_REQUEST(const E1AP_E1AP_PDU_t *pdu, e1ap_bearer_mod_req_t *bearerCxt)
|
||||
{
|
||||
const E1AP_BearerContextModificationRequest_t *in = &pdu->choice.initiatingMessage->value.choice.BearerContextModificationRequest;
|
||||
E1AP_BearerContextModificationRequestIEs_t *ie;
|
||||
|
||||
LOG_D(E1AP, "Bearer context setup number of IEs %d\n", in->protocolIEs.list.count);
|
||||
|
||||
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:
|
||||
DevAssert(ie->criticality == E1AP_Criticality_reject);
|
||||
DevAssert(ie->value.present == E1AP_BearerContextModificationRequestIEs__value_PR_GNB_CU_CP_UE_E1AP_ID);
|
||||
bearerCxt->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:
|
||||
DevAssert(ie->criticality == E1AP_Criticality_reject);
|
||||
DevAssert(ie->value.present == E1AP_BearerContextModificationRequestIEs__value_PR_GNB_CU_UP_UE_E1AP_ID);
|
||||
bearerCxt->gNB_cu_up_ue_id = ie->value.choice.GNB_CU_UP_UE_E1AP_ID;
|
||||
break;
|
||||
|
||||
case E1AP_ProtocolIE_ID_id_SecurityInformation: {
|
||||
DevAssert(ie->criticality == E1AP_Criticality_reject);
|
||||
DevAssert(ie->value.present == E1AP_BearerContextModificationRequestIEs__value_PR_SecurityInformation);
|
||||
E1AP_SecurityInformation_t *sec = &ie->value.choice.SecurityInformation;
|
||||
DevAssert(sec->uPSecuritykey.encryptionKey.size == E1AP_SECURITY_KEY_SIZE);
|
||||
DevAssert(sec->uPSecuritykey.integrityProtectionKey == NULL
|
||||
|| sec->uPSecuritykey.integrityProtectionKey->size == E1AP_SECURITY_KEY_SIZE);
|
||||
bearerCxt->secInfo = malloc_or_fail(sizeof(*bearerCxt->secInfo));
|
||||
bearerCxt->secInfo->cipheringAlgorithm = sec->securityAlgorithm.cipheringAlgorithm;
|
||||
bearerCxt->secInfo->integrityProtectionAlgorithm = sec->securityAlgorithm.integrityProtectionAlgorithm == NULL
|
||||
? 0
|
||||
: *sec->securityAlgorithm.integrityProtectionAlgorithm;
|
||||
memcpy(bearerCxt->secInfo->encryptionKey, sec->uPSecuritykey.encryptionKey.buf, E1AP_SECURITY_KEY_SIZE);
|
||||
if (sec->securityAlgorithm.integrityProtectionAlgorithm == NULL)
|
||||
memset(bearerCxt->secInfo->integrityProtectionKey, 0, E1AP_SECURITY_KEY_SIZE);
|
||||
else
|
||||
memcpy(bearerCxt->secInfo->integrityProtectionKey, sec->uPSecuritykey.integrityProtectionKey->buf, E1AP_SECURITY_KEY_SIZE);
|
||||
break;
|
||||
}
|
||||
|
||||
case E1AP_ProtocolIE_ID_id_System_BearerContextModificationRequest:
|
||||
DevAssert(ie->criticality == E1AP_Criticality_reject);
|
||||
DevAssert(ie->value.present == E1AP_BearerContextModificationRequestIEs__value_PR_System_BearerContextModificationRequest);
|
||||
DevAssert(ie->value.choice.System_BearerContextModificationRequest.present ==
|
||||
E1AP_System_BearerContextModificationRequest_PR_nG_RAN_BearerContextModificationRequest);
|
||||
DevAssert(ie->value.choice.System_BearerContextModificationRequest.choice.nG_RAN_BearerContextModificationRequest != NULL);
|
||||
E1AP_ProtocolIE_Container_4932P26_t *msgNGRAN_list = (E1AP_ProtocolIE_Container_4932P26_t *) ie->value.choice.System_BearerContextModificationRequest.choice.nG_RAN_BearerContextModificationRequest;
|
||||
E1AP_NG_RAN_BearerContextModificationRequest_t *msgNGRAN = msgNGRAN_list->list.array[0];
|
||||
DevAssert(msgNGRAN_list->list.count == 1);
|
||||
DevAssert(msgNGRAN->id == E1AP_ProtocolIE_ID_id_PDU_Session_Resource_To_Modify_List);
|
||||
DevAssert(msgNGRAN->value.present =
|
||||
E1AP_NG_RAN_BearerContextModificationRequest__value_PR_PDU_Session_Resource_To_Modify_List);
|
||||
/* PDU Session Resource To Modify List (see 9.3.3.11 of TS 38.463) */
|
||||
E1AP_PDU_Session_Resource_To_Modify_List_t *pdu2ModList = &msgNGRAN->value.choice.PDU_Session_Resource_To_Modify_List;
|
||||
bearerCxt->numPDUSessionsMod = pdu2ModList->list.count;
|
||||
for (int i = 0; i < pdu2ModList->list.count; i++) {
|
||||
pdu_session_to_mod_t *pdu_session = bearerCxt->pduSessionMod + i;
|
||||
E1AP_PDU_Session_Resource_To_Modify_Item_t *pdu2Mod = pdu2ModList->list.array[i];
|
||||
pdu_session->sessionId = pdu2Mod->pDU_Session_ID;
|
||||
E1AP_DRB_To_Modify_List_NG_RAN_t *drb2ModList = pdu2Mod->dRB_To_Modify_List_NG_RAN;
|
||||
pdu_session->numDRB2Modify = drb2ModList->list.count;
|
||||
/* DRBs to modify */
|
||||
for (int j = 0; j < drb2ModList->list.count; j++) {
|
||||
DRB_nGRAN_to_mod_t *drb = pdu_session->DRBnGRanModList + j;
|
||||
E1AP_DRB_To_Modify_Item_NG_RAN_t *drb2Mod = drb2ModList->list.array[j];
|
||||
drb->id = drb2Mod->dRB_ID;
|
||||
if (drb2Mod->pDCP_Configuration != NULL
|
||||
&& drb2Mod->pDCP_Configuration->pDCP_Reestablishment != NULL
|
||||
&& *drb2Mod->pDCP_Configuration->pDCP_Reestablishment == E1AP_PDCP_Reestablishment_true) {
|
||||
drb->pdcp_config = malloc_or_fail(sizeof(*drb->pdcp_config));
|
||||
drb->pdcp_config->pDCP_Reestablishment = true;
|
||||
}
|
||||
if (drb2Mod->dL_UP_Parameters) { /* Optional IE in the DRB To Modify Item */
|
||||
E1AP_UP_Parameters_t *dl_up_paramList = drb2Mod->dL_UP_Parameters;
|
||||
drb->numDlUpParam = dl_up_paramList->list.count;
|
||||
for (int k = 0; k < dl_up_paramList->list.count; k++) {
|
||||
up_params_t *dl_up_param = drb->DlUpParamList + k;
|
||||
E1AP_UP_Parameters_Item_t *dl_up_param_in = dl_up_paramList->list.array[k];
|
||||
if (dl_up_param_in->uP_TNL_Information.choice.gTPTunnel) { // Optional IE
|
||||
DevAssert(dl_up_param_in->uP_TNL_Information.present = E1AP_UP_TNL_Information_PR_gTPTunnel);
|
||||
BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(
|
||||
&dl_up_param_in->uP_TNL_Information.choice.gTPTunnel->transportLayerAddress,
|
||||
dl_up_param->tl_info.tlAddress);
|
||||
OCTET_STRING_TO_INT32(&dl_up_param_in->uP_TNL_Information.choice.gTPTunnel->gTP_TEID, dl_up_param->tl_info.teId);
|
||||
} else {
|
||||
AssertFatal(false, "gTPTunnel IE is missing. It is mandatory at this point\n");
|
||||
}
|
||||
dl_up_param->cell_group_id = dl_up_param_in->cell_Group_ID;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case E1AP_ProtocolIE_ID_id_BearerContextStatusChange:
|
||||
/* Bearer Context Status Change */
|
||||
DevAssert(ie->criticality == E1AP_Criticality_reject);
|
||||
DevAssert(ie->value.present == E1AP_BearerContextModificationRequestIEs__value_PR_BearerContextStatusChange);
|
||||
bearerCxt->bearerContextStatus = malloc_or_fail(*bearerCxt->bearerContextStatus);
|
||||
*bearerCxt->bearerContextStatus = (ie->value.choice.BearerContextStatusChange == E1AP_BearerContextStatusChange_suspend) ? BEARER_SUSPEND : BEARER_ACTIVE;
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG_E(E1AP, "Handle for this IE is not implemented (or) invalid IE detected\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Extract Bearer Context Modification Request from E1AP PDU
|
||||
* and prepare Bearer Context Modification Response
|
||||
@@ -720,99 +453,27 @@ int e1apCUUP_handle_BEARER_CONTEXT_MODIFICATION_REQUEST(sctp_assoc_t assoc_id,
|
||||
e1ap_upcp_inst_t *e1_inst,
|
||||
const E1AP_E1AP_PDU_t *pdu)
|
||||
{
|
||||
DevAssert(pdu != NULL);
|
||||
DevAssert(pdu->present == E1AP_E1AP_PDU_PR_initiatingMessage);
|
||||
DevAssert(pdu->choice.initiatingMessage->procedureCode == E1AP_ProcedureCode_id_bearerContextModification);
|
||||
DevAssert(pdu->choice.initiatingMessage->criticality == E1AP_Criticality_reject);
|
||||
DevAssert(pdu->choice.initiatingMessage->value.present == E1AP_InitiatingMessage__value_PR_BearerContextModificationRequest);
|
||||
e1ap_bearer_mod_req_t bearerCxt = {0};
|
||||
extract_BEARER_CONTEXT_MODIFICATION_REQUEST(pdu, &bearerCxt);
|
||||
e1_bearer_context_modif(&bearerCxt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void extract_BEARER_CONTEXT_MODIFICATION_RESPONSE(const E1AP_E1AP_PDU_t *pdu, e1ap_bearer_modif_resp_t *resp)
|
||||
{
|
||||
memset(resp, 0, sizeof(*resp));
|
||||
const E1AP_BearerContextModificationResponse_t *in =
|
||||
&pdu->choice.successfulOutcome->value.choice.BearerContextModificationResponse;
|
||||
|
||||
for (int i = 0; i < in->protocolIEs.list.count; ++i) {
|
||||
E1AP_BearerContextModificationResponseIEs_t *ie = in->protocolIEs.list.array[i];
|
||||
|
||||
switch (ie->id) {
|
||||
case E1AP_ProtocolIE_ID_id_gNB_CU_CP_UE_E1AP_ID:
|
||||
DevAssert(ie->criticality == E1AP_Criticality_reject);
|
||||
DevAssert(ie->value.present == E1AP_BearerContextModificationResponseIEs__value_PR_GNB_CU_CP_UE_E1AP_ID);
|
||||
resp->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:
|
||||
DevAssert(ie->criticality == E1AP_Criticality_reject);
|
||||
DevAssert(ie->value.present == E1AP_BearerContextModificationResponseIEs__value_PR_GNB_CU_UP_UE_E1AP_ID);
|
||||
resp->gNB_cu_up_ue_id = ie->value.choice.GNB_CU_UP_UE_E1AP_ID;
|
||||
break;
|
||||
|
||||
case E1AP_ProtocolIE_ID_id_System_BearerContextModificationResponse:
|
||||
DevAssert(ie->criticality == E1AP_Criticality_ignore);
|
||||
DevAssert(ie->value.present
|
||||
== E1AP_BearerContextModificationResponseIEs__value_PR_System_BearerContextModificationResponse);
|
||||
DevAssert(ie->value.choice.System_BearerContextModificationResponse.present
|
||||
== E1AP_System_BearerContextModificationResponse_PR_nG_RAN_BearerContextModificationResponse);
|
||||
E1AP_ProtocolIE_Container_4932P29_t *msgNGRAN_list =
|
||||
(E1AP_ProtocolIE_Container_4932P29_t *)
|
||||
ie->value.choice.System_BearerContextModificationResponse.choice.nG_RAN_BearerContextModificationResponse;
|
||||
DevAssert(msgNGRAN_list->list.count == 1);
|
||||
E1AP_NG_RAN_BearerContextModificationResponse_t *msgNGRAN = msgNGRAN_list->list.array[0];
|
||||
DevAssert(msgNGRAN->id == E1AP_ProtocolIE_ID_id_PDU_Session_Resource_Modified_List);
|
||||
DevAssert(msgNGRAN->criticality == E1AP_Criticality_reject);
|
||||
DevAssert(msgNGRAN->value.present
|
||||
== E1AP_NG_RAN_BearerContextModificationResponse__value_PR_PDU_Session_Resource_Modified_List);
|
||||
E1AP_PDU_Session_Resource_Modified_List_t *pduModifiedList = &msgNGRAN->value.choice.PDU_Session_Resource_Modified_List;
|
||||
resp->numPDUSessionsMod = pduModifiedList->list.count;
|
||||
|
||||
for (int i = 0; i < pduModifiedList->list.count; i++) {
|
||||
pdu_session_modif_t *pduModified = &resp->pduSessionMod[i];
|
||||
E1AP_PDU_Session_Resource_Modified_Item_t *mod_it = pduModifiedList->list.array[i];
|
||||
pduModified->id = mod_it->pDU_Session_ID;
|
||||
|
||||
AssertFatal(mod_it->nG_DL_UP_TNL_Information == NULL, "not implemented\n");
|
||||
AssertFatal(mod_it->securityResult == NULL, "not implemented\n");
|
||||
AssertFatal(mod_it->pDU_Session_Data_Forwarding_Information_Response == NULL, "not implemented\n");
|
||||
AssertFatal(mod_it->dRB_Setup_List_NG_RAN == NULL, "not implemented\n");
|
||||
AssertFatal(mod_it->dRB_Failed_List_NG_RAN == NULL, "not implemented\n");
|
||||
AssertFatal(mod_it->dRB_Failed_To_Modify_List_NG_RAN == NULL, "not implemented\n");
|
||||
|
||||
pduModified->numDRBModified = mod_it->dRB_Modified_List_NG_RAN->list.count;
|
||||
for (int j = 0; j < mod_it->dRB_Modified_List_NG_RAN->list.count; j++) {
|
||||
DRB_nGRAN_modified_t *drbModified = &pduModified->DRBnGRanModList[j];
|
||||
E1AP_DRB_Modified_Item_NG_RAN_t *drb = mod_it->dRB_Modified_List_NG_RAN->list.array[j];
|
||||
|
||||
drbModified->id = drb->dRB_ID;
|
||||
|
||||
AssertFatal(drb->uL_UP_Transport_Parameters == NULL, "not implemented\n");
|
||||
AssertFatal(drb->pDCP_SN_Status_Information == NULL, "not implemented\n");
|
||||
AssertFatal(drb->flow_Setup_List == NULL, "not implemented\n");
|
||||
AssertFatal(drb->flow_Failed_List == NULL, "not implemented\n");
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!decode_E1_bearer_context_mod_request(pdu, &bearerCxt)) {
|
||||
LOG_E(E1AP, "Failed to handle Bearer Context Modification Request\n");
|
||||
free_e1ap_context_mod_request(&bearerCxt);
|
||||
return -1;
|
||||
}
|
||||
e1_bearer_context_modif(&bearerCxt);
|
||||
free_e1ap_context_mod_request(&bearerCxt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int e1apCUCP_handle_BEARER_CONTEXT_MODIFICATION_RESPONSE(sctp_assoc_t assoc_id,
|
||||
e1ap_upcp_inst_t *e1_inst,
|
||||
const E1AP_E1AP_PDU_t *pdu)
|
||||
{
|
||||
DevAssert(pdu != NULL);
|
||||
DevAssert(pdu->present == E1AP_E1AP_PDU_PR_successfulOutcome);
|
||||
DevAssert(pdu->choice.successfulOutcome->procedureCode == E1AP_ProcedureCode_id_bearerContextModification);
|
||||
DevAssert(pdu->choice.successfulOutcome->criticality == E1AP_Criticality_reject);
|
||||
DevAssert(pdu->choice.successfulOutcome->value.present == E1AP_SuccessfulOutcome__value_PR_BearerContextModificationResponse);
|
||||
MessageDef *msg = itti_alloc_new_message(TASK_CUUP_E1, 0, E1AP_BEARER_CONTEXT_MODIFICATION_RESP);
|
||||
e1ap_bearer_modif_resp_t *modif = &E1AP_BEARER_CONTEXT_MODIFICATION_RESP(msg);
|
||||
extract_BEARER_CONTEXT_MODIFICATION_RESPONSE(pdu, modif);
|
||||
if(!decode_E1_bearer_context_mod_response(modif, pdu)) {
|
||||
free_e1ap_context_mod_response(modif);
|
||||
return -1;
|
||||
}
|
||||
itti_send_msg_to_task(TASK_RRC_GNB, 0, msg);
|
||||
return 0;
|
||||
}
|
||||
@@ -1296,6 +957,7 @@ void *E1AP_CUCP_task(void *arg)
|
||||
|
||||
case E1AP_BEARER_CONTEXT_MODIFICATION_REQ:
|
||||
e1apCUCP_send_BEARER_CONTEXT_MODIFICATION_REQUEST(assoc_id, &E1AP_BEARER_CONTEXT_MODIFICATION_REQ(msg));
|
||||
free_e1ap_context_mod_request(&E1AP_BEARER_CONTEXT_MODIFICATION_REQ(msg));
|
||||
break;
|
||||
|
||||
case E1AP_BEARER_CONTEXT_RELEASE_CMD:
|
||||
@@ -1371,6 +1033,7 @@ void *E1AP_CUUP_task(void *arg)
|
||||
const e1ap_upcp_inst_t *inst = getCxtE1(myInstance);
|
||||
AssertFatal(inst, "no E1 instance found for instance %ld\n", myInstance);
|
||||
e1apCUUP_send_BEARER_CONTEXT_MODIFICATION_RESPONSE(inst->cuup.assoc_id, resp);
|
||||
free_e1ap_context_mod_response(resp);
|
||||
} break;
|
||||
|
||||
case E1AP_BEARER_CONTEXT_RELEASE_CPLT: {
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "common/utils/assertions.h"
|
||||
#include "openair3/UTILS/conversions.h"
|
||||
@@ -83,19 +84,29 @@ static E1AP_SecurityInformation_t e1_encode_security_info(const security_informa
|
||||
return ie;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Decode E1AP_SecurityInformation_t
|
||||
*/
|
||||
/** @brief Decode Security Information IE (3GPP TS 38.463, 9.3.1.10) */
|
||||
static bool e1_decode_security_info(security_information_t *out, const E1AP_SecurityInformation_t *in)
|
||||
{
|
||||
// Security Algorithm (M) (9.3.1.31)
|
||||
// Ciphering Algorithm (M)
|
||||
out->cipheringAlgorithm = in->securityAlgorithm.cipheringAlgorithm;
|
||||
// Integrity Protection Algorithm (O)
|
||||
out->integrityProtectionAlgorithm =
|
||||
in->securityAlgorithm.integrityProtectionAlgorithm == NULL ? 0 : *in->securityAlgorithm.integrityProtectionAlgorithm;
|
||||
|
||||
// User Plane Security Keys (M) (9.3.1.32)
|
||||
// Encryption Key (M)
|
||||
_E1_EQ_CHECK_INT((int)in->uPSecuritykey.encryptionKey.size, E1AP_SECURITY_KEY_SIZE);
|
||||
memcpy(out->encryptionKey, in->uPSecuritykey.encryptionKey.buf, in->uPSecuritykey.encryptionKey.size);
|
||||
if (in->securityAlgorithm.integrityProtectionAlgorithm)
|
||||
out->integrityProtectionAlgorithm = *in->securityAlgorithm.integrityProtectionAlgorithm;
|
||||
// Integrity Protection Key (O)
|
||||
if (in->uPSecuritykey.integrityProtectionKey) {
|
||||
E1AP_IntegrityProtectionKey_t *ipKey = in->uPSecuritykey.integrityProtectionKey;
|
||||
memcpy(out->integrityProtectionKey, ipKey->buf, ipKey->size);
|
||||
_E1_EQ_CHECK_INT((int)ipKey->size, E1AP_SECURITY_KEY_SIZE);
|
||||
memcpy(out->integrityProtectionKey, ipKey->buf, E1AP_SECURITY_KEY_SIZE);
|
||||
} else {
|
||||
memset(out->integrityProtectionKey, 0, E1AP_SECURITY_KEY_SIZE);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -515,7 +526,7 @@ static bool eq_pdu_session_item(const pdu_session_to_setup_t *a, const pdu_sessi
|
||||
return false;
|
||||
_E1_EQ_CHECK_OPTIONAL_PTR(a, b, inactivityTimer);
|
||||
if (a->inactivityTimer && b->inactivityTimer)
|
||||
_E1_EQ_CHECK_INT(a->inactivityTimer, b->inactivityTimer);
|
||||
_E1_EQ_CHECK_INT(*a->inactivityTimer, *b->inactivityTimer);
|
||||
_E1_EQ_CHECK_OPTIONAL_IE(a, b, dlAggregateMaxBitRate, _E1_EQ_CHECK_LONG);
|
||||
return true;
|
||||
}
|
||||
@@ -766,11 +777,31 @@ bool eq_bearer_context_setup_request(const e1ap_bearer_setup_req_t *a, const e1a
|
||||
// Check optional IEs
|
||||
_E1_EQ_CHECK_OPTIONAL_PTR(a, b, inactivityTimerUE);
|
||||
if (a->inactivityTimerUE && b->inactivityTimerUE)
|
||||
_E1_EQ_CHECK_INT(a->inactivityTimerUE, b->inactivityTimerUE);
|
||||
_E1_EQ_CHECK_INT(*a->inactivityTimerUE, *b->inactivityTimerUE);
|
||||
_E1_EQ_CHECK_OPTIONAL_IE(a, b, ueDlMaxIPBitRate, _E1_EQ_CHECK_LONG);
|
||||
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
|
||||
* ====================================== */
|
||||
@@ -808,13 +839,9 @@ static bool e1_decode_pdu_session_setup_item(pdu_session_setup_t *pduSetup, E1AP
|
||||
}
|
||||
// DRB Failed to Setup List (O)
|
||||
if (in->dRB_Failed_List_NG_RAN) {
|
||||
pduSetup->numDRBFailed = in->dRB_Failed_List_NG_RAN->list.count;
|
||||
for (int j = 0; j < in->dRB_Failed_List_NG_RAN->list.count; j++) {
|
||||
DRB_nGRAN_failed_t *drbFailed = pduSetup->DRBnGRanFailedList + j;
|
||||
E1AP_DRB_Failed_Item_NG_RAN_t *item = in->dRB_Failed_List_NG_RAN->list.array[j];
|
||||
// DRB ID (M)
|
||||
drbFailed->id = item->dRB_ID;
|
||||
// Cause (M)
|
||||
drbFailed->cause = e1_decode_cause_ie(&item->cause);
|
||||
decode_drb_failed_item(&pduSetup->DRBnGRanFailedList[j], in->dRB_Failed_List_NG_RAN->list.array[j]);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@@ -848,10 +875,7 @@ static bool e1_encode_pdu_session_setup_item(E1AP_PDU_Session_Resource_Setup_Ite
|
||||
// DRB Failed Item
|
||||
for (const DRB_nGRAN_failed_t *j = in->DRBnGRanFailedList; j < in->DRBnGRanFailedList + in->numDRBFailed; j++) {
|
||||
asn1cSequenceAdd(item->dRB_Failed_List_NG_RAN->list, E1AP_DRB_Failed_Item_NG_RAN_t, ieC3_1_1);
|
||||
// DRB ID (M)
|
||||
ieC3_1_1->dRB_ID = j->id;
|
||||
// Cause (M)
|
||||
ieC3_1_1->cause = e1_encode_cause_ie(&j->cause);
|
||||
encode_drb_failed_item(ieC3_1_1, j);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -1036,8 +1060,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;
|
||||
@@ -1349,10 +1373,12 @@ static bool e1_decode_pdu_session_to_mod_item(pdu_session_to_mod_t *out, const E
|
||||
}
|
||||
}
|
||||
// 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]));
|
||||
if (drb2Mod->flow_Mapping_Information) {
|
||||
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;
|
||||
@@ -1494,7 +1520,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;
|
||||
}
|
||||
@@ -1680,3 +1706,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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,4 +46,10 @@ 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);
|
||||
|
||||
struct E1AP_E1AP_PDU *encode_E1_bearer_context_mod_response(const e1ap_bearer_modif_resp_t *msg);
|
||||
bool decode_E1_bearer_context_mod_response(e1ap_bearer_modif_resp_t *out, const struct E1AP_E1AP_PDU *pdu);
|
||||
void free_e1ap_context_mod_response(const e1ap_bearer_modif_resp_t *msg);
|
||||
e1ap_bearer_modif_resp_t cp_bearer_context_mod_response(const e1ap_bearer_modif_resp_t *msg);
|
||||
bool eq_bearer_context_mod_response(const e1ap_bearer_modif_resp_t *a, const e1ap_bearer_modif_resp_t *b);
|
||||
|
||||
#endif /* E1AP_BEARER_CONTEXT_MANAGEMENT_H_ */
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
#include "e1ap_messages_types.h"
|
||||
|
||||
#ifdef E1AP_LOG_ERRORS
|
||||
#define PRINT_ERROR(...) fprintf(stderr, ##__VA_ARGS__);
|
||||
#define PRINT_ERROR(fmt, ...) fprintf(stderr, "[%s] " fmt, __func__, ##__VA_ARGS__)
|
||||
#else
|
||||
#define PRINT_ERROR(...) // Do nothing
|
||||
#endif
|
||||
|
||||
@@ -41,6 +41,11 @@
|
||||
#include "E1AP_Cell-Group-Information-Item.h"
|
||||
#include "E1AP_Dynamic5QIDescriptor.h"
|
||||
#include "E1AP_Non-Dynamic5QIDescriptor.h"
|
||||
#include "E1AP_SecurityResult.h"
|
||||
#include "E1AP_Data-Forwarding-Information.h"
|
||||
#include "E1AP_PDCP-SN-Status-Information.h"
|
||||
#include "E1AP_PDCP-Count.h"
|
||||
|
||||
// E1 Bearer Context Setup Request
|
||||
#include "E1AP_BearerContextSetupRequest.h"
|
||||
#include "E1AP_GNB-CU-CP-E1SetupRequest.h"
|
||||
@@ -73,5 +78,13 @@
|
||||
#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"
|
||||
// E1 Bearer Context Modification Response
|
||||
#include "E1AP_PDU-Session-Resource-Modified-Item.h"
|
||||
#include "E1AP_DRB-Modified-List-NG-RAN.h"
|
||||
#include "E1AP_DRB-Modified-Item-NG-RAN.h"
|
||||
#include "E1AP_DRB-Failed-To-Modify-List-NG-RAN.h"
|
||||
#include "E1AP_QoS-Flow-Failed-List.h"
|
||||
#include "E1AP_QoS-Flow-Failed-Item.h"
|
||||
#include "E1AP_DRB-Failed-To-Modify-Item-NG-RAN.h"
|
||||
|
||||
#endif /* E1AP_LIB_INCLUDES_H_ */
|
||||
|
||||
@@ -453,6 +453,170 @@ static void test_bearer_context_modification_request(void)
|
||||
free_e1ap_context_mod_request(&orig);
|
||||
}
|
||||
|
||||
const e1ap_cause_t dummy_cause = {
|
||||
.value = E1AP_RADIO_CAUSE_UNSPECIFIED,
|
||||
.type = E1AP_CAUSE_RADIO_NETWORK,
|
||||
};
|
||||
|
||||
const DRB_nGRAN_failed_t dummy_drb_failed = {
|
||||
.id = 2,
|
||||
.cause.value = E1AP_RADIO_CAUSE_UNKNOWN_DRB_ID,
|
||||
.cause.type = E1AP_CAUSE_RADIO_NETWORK,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Test E1AP Bearer Context Modification Response encoding/decoding
|
||||
*/
|
||||
static void test_bearer_context_modification_response(void)
|
||||
{
|
||||
// DRB Modified List
|
||||
DRB_nGRAN_modified_t drb_mod = {
|
||||
.id = 1,
|
||||
.numQosFlowSetup = 1,
|
||||
.qosFlows[0].qfi = 1,
|
||||
};
|
||||
|
||||
// DRB Setup List
|
||||
DRB_nGRAN_setup_t setup = {
|
||||
.id = 1,
|
||||
.numUpParam = 1,
|
||||
.UpParamList[0].cell_group_id = MCG,
|
||||
.UpParamList[0].tl_info = create_up_tl_info(),
|
||||
.numQosFlowSetup = 1,
|
||||
.qosFlows[0].qfi = 1,
|
||||
.numQosFlowFailed = 1,
|
||||
.qosFlowsFailed[0].qfi = 9,
|
||||
.qosFlowsFailed[0].cause = dummy_cause,
|
||||
};
|
||||
|
||||
// PDU Session Modified
|
||||
pdu_session_modif_t pdu_mod = {
|
||||
.id = 1,
|
||||
.integrityProtectionIndication = malloc_or_fail(sizeof(*pdu_mod.integrityProtectionIndication)),
|
||||
.confidentialityProtectionIndication = malloc_or_fail(sizeof(*pdu_mod.confidentialityProtectionIndication)),
|
||||
.ng_DL_UP_TL_info = malloc_or_fail(sizeof(*pdu_mod.ng_DL_UP_TL_info)),
|
||||
.numDRBModified = 1,
|
||||
.DRBnGRanModList[0] = drb_mod,
|
||||
.numDRBFailedToMod = 1,
|
||||
.DRBnGRanFailedModList[0] = dummy_drb_failed,
|
||||
.numDRBSetup = 1,
|
||||
.DRBnGRanSetupList[0] = setup,
|
||||
.numDRBFailed = 1,
|
||||
.DRBnGRanFailedList[0] = dummy_drb_failed,
|
||||
};
|
||||
|
||||
*pdu_mod.integrityProtectionIndication = SECURITY_PREFERRED;
|
||||
*pdu_mod.confidentialityProtectionIndication = SECURITY_PREFERRED;
|
||||
*pdu_mod.ng_DL_UP_TL_info = create_up_tl_info();
|
||||
|
||||
e1ap_bearer_modif_resp_t orig = {
|
||||
.gNB_cu_cp_ue_id = 0x1234,
|
||||
.gNB_cu_up_ue_id = 0x5678,
|
||||
.numPDUSessionsMod = 1,
|
||||
.pduSessionMod[0] = pdu_mod,
|
||||
};
|
||||
|
||||
// Encode the original message
|
||||
E1AP_E1AP_PDU_t *enc = encode_E1_bearer_context_mod_response(&orig);
|
||||
|
||||
// Decode the encoded message
|
||||
E1AP_E1AP_PDU_t *dec = e1ap_encode_decode(enc);
|
||||
|
||||
// Free the encoded message
|
||||
e1ap_msg_free(enc);
|
||||
|
||||
// Decode the message into a new struct
|
||||
e1ap_bearer_modif_resp_t decoded = {0};
|
||||
bool ret = decode_E1_bearer_context_mod_response(&decoded, dec);
|
||||
AssertFatal(ret, "decode_E1_bearer_context_mod_response(): could not decode message\n");
|
||||
|
||||
// Free the decoded E1AP message
|
||||
e1ap_msg_free(dec);
|
||||
|
||||
// Compare the original and decoded structs
|
||||
ret = eq_bearer_context_mod_response(&orig, &decoded);
|
||||
AssertFatal(ret, "eq_bearer_context_mod_response(): decoded message doesn't match\n");
|
||||
|
||||
// Free the memory for the decoded message
|
||||
free_e1ap_context_mod_response(&decoded);
|
||||
|
||||
// Deep copy the original message
|
||||
e1ap_bearer_modif_resp_t cp = cp_bearer_context_mod_response(&orig);
|
||||
|
||||
// Verify the deep copy matches the original
|
||||
ret = eq_bearer_context_mod_response(&orig, &cp);
|
||||
AssertFatal(ret, "eq_bearer_context_mod_response(): copied message doesn't match\n");
|
||||
|
||||
// Free the copied and original message
|
||||
free_e1ap_context_mod_response(&cp);
|
||||
free_e1ap_context_mod_response(&orig);
|
||||
}
|
||||
|
||||
/** @brief Test E1AP Bearer Context Modification Response encoding/decoding
|
||||
* with failed DRBs (setup and modification) */
|
||||
static void test_bearer_context_modification_response_fail(void)
|
||||
{
|
||||
const e1ap_cause_t cause = {
|
||||
.value = E1AP_PROTOCOL_CAUSE_SEMANTIC_ERROR,
|
||||
.type = E1AP_CAUSE_PROTOCOL,
|
||||
};
|
||||
|
||||
DRB_nGRAN_failed_t failed_setup_drb = {
|
||||
.id = 5,
|
||||
.cause = cause,
|
||||
};
|
||||
|
||||
DRB_nGRAN_failed_t failed_mod_drb = {
|
||||
.id = 6,
|
||||
.cause = cause,
|
||||
};
|
||||
|
||||
pdu_session_modif_t pdu_mod = {
|
||||
.id = 2,
|
||||
.numDRBModified = 0,
|
||||
.numDRBFailedToMod = 1,
|
||||
.DRBnGRanFailedModList[0] = failed_mod_drb,
|
||||
.numDRBSetup = 0,
|
||||
.numDRBFailed = 1,
|
||||
.DRBnGRanFailedList[0] = failed_setup_drb,
|
||||
.integrityProtectionIndication = NULL,
|
||||
.confidentialityProtectionIndication = NULL,
|
||||
.ng_DL_UP_TL_info = NULL,
|
||||
};
|
||||
|
||||
e1ap_bearer_modif_resp_t orig = {
|
||||
.gNB_cu_cp_ue_id = 0xABCD,
|
||||
.gNB_cu_up_ue_id = 0xDCBA,
|
||||
.numPDUSessionsMod = 1,
|
||||
.pduSessionMod[0] = pdu_mod,
|
||||
};
|
||||
|
||||
// Encode the original message
|
||||
E1AP_E1AP_PDU_t *enc = encode_E1_bearer_context_mod_response(&orig);
|
||||
|
||||
// Decode the encoded message
|
||||
E1AP_E1AP_PDU_t *dec = e1ap_encode_decode(enc);
|
||||
|
||||
// Free the encoded message
|
||||
e1ap_msg_free(enc);
|
||||
|
||||
// Decode into a new struct
|
||||
e1ap_bearer_modif_resp_t decoded = {0};
|
||||
bool ret = decode_E1_bearer_context_mod_response(&decoded, dec);
|
||||
AssertFatal(ret, "decode_E1_bearer_context_mod_response(): could not decode failed DRB setup+mod case\n");
|
||||
|
||||
// Free the decoded E1AP message
|
||||
e1ap_msg_free(dec);
|
||||
|
||||
// Compare the original and decoded structs
|
||||
ret = eq_bearer_context_mod_response(&orig, &decoded);
|
||||
AssertFatal(ret, "eq_bearer_context_mod_response(): failed DRB setup+mod case mismatch\n");
|
||||
|
||||
// Free all memory
|
||||
free_e1ap_context_mod_response(&decoded);
|
||||
free_e1ap_context_mod_response(&orig);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
// E1 Bearer Context Setup
|
||||
@@ -464,5 +628,7 @@ int main()
|
||||
test_e1_cuup_setup_failure();
|
||||
// E1 Bearer Context Modification Request
|
||||
test_bearer_context_modification_request();
|
||||
test_bearer_context_modification_response();
|
||||
test_bearer_context_modification_response_fail();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ static void cucp_cuup_bearer_context_mod_e1ap(sctp_assoc_t assoc_id, const e1ap_
|
||||
MessageDef *msg = itti_alloc_new_message(TASK_CUCP_E1, 0, E1AP_BEARER_CONTEXT_MODIFICATION_REQ);
|
||||
msg->ittiMsgHeader.originInstance = assoc_id;
|
||||
e1ap_bearer_mod_req_t *req_msg = &E1AP_BEARER_CONTEXT_MODIFICATION_REQ(msg);
|
||||
memcpy(req_msg, req, sizeof(*req));
|
||||
*req_msg = cp_bearer_context_mod_request(req);
|
||||
itti_send_msg_to_task(TASK_CUCP_E1, 0, msg);
|
||||
}
|
||||
|
||||
|
||||
@@ -2866,6 +2866,7 @@ void *rrc_gnb_task(void *args_p) {
|
||||
|
||||
case E1AP_BEARER_CONTEXT_MODIFICATION_RESP:
|
||||
rrc_gNB_process_e1_bearer_context_modif_resp(&E1AP_BEARER_CONTEXT_MODIFICATION_RESP(msg_p));
|
||||
free_e1ap_context_mod_response(&E1AP_BEARER_CONTEXT_MODIFICATION_RESP(msg_p));
|
||||
break;
|
||||
|
||||
case E1AP_BEARER_CONTEXT_RELEASE_CPLT:
|
||||
|
||||
Reference in New Issue
Block a user