Merge remote-tracking branch 'origin/e1ap-lib-improvements' into integration_2025_w06 (!3219)
E1AP enc/dec lib improvements This MR is including some fixes and improvements for the E1AP library, focusing mostly on Bearer Context Management: - struct reorganization: split setup and modification request messages into distinct structures, ensuring compliance with 3GPP TS 38.463 specifications - add encoding/decoding sub-functions for different IEs - improvements to Bearer Context Management: Implemented various improvements to the E1 Bearer Context Setup Response and Request, including the adoption of encoding/decoding sub-functions for different IEs - use lib functions whenever need (e.g. cp_bearer_context_setup_request in cucp_cuup_e1ap.c) - handle optional struct members as pointers - updated copy/equality check utility functions EDIT: The MR is also including the changes from !3222 (closed): > While testing E1 with security enabled for DRBs, it was found that > data traffic was not functional. > > The problem was that security settings were modified in the PDCP > reestablishment happening when receiving Bearer Context Modification > Request. > > So some restructuring was done. > > The actual fix is in 18176297, the others are for support. Basically > we introduce a boolean to check if the security settings are present in > Bearer Context Modification Request and we change PDCP security settings > only if they are. > > (Note that in OAI CU security settings are not sent in Bearer Context > Modification Request, so we could also remove all this, but we need to > be compatible with other cu-up and/or cu-cp.)
This commit is contained in:
@@ -10,3 +10,7 @@ target_include_directories(e1ap PUBLIC ${CMAKE_CURRENT_DIR})
|
||||
if(ENABLE_TESTS)
|
||||
add_subdirectory(tests)
|
||||
endif()
|
||||
|
||||
if(ENABLE_TESTS)
|
||||
target_compile_definitions(e1ap PRIVATE E1AP_LOG_ERRORS)
|
||||
endif()
|
||||
|
||||
+48
-11
@@ -431,7 +431,7 @@ int e1apCUCP_handle_BEARER_CONTEXT_SETUP_FAILURE(sctp_assoc_t assoc_id, e1ap_upc
|
||||
BEARER CONTEXT MODIFICATION REQUEST
|
||||
*/
|
||||
|
||||
static int fill_BEARER_CONTEXT_MODIFICATION_REQUEST(e1ap_bearer_setup_req_t *const bearerCxt, E1AP_E1AP_PDU_t *pdu)
|
||||
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);
|
||||
@@ -453,6 +453,21 @@ static int fill_BEARER_CONTEXT_MODIFICATION_REQUEST(e1ap_bearer_setup_req_t *con
|
||||
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);
|
||||
@@ -475,7 +490,7 @@ static int fill_BEARER_CONTEXT_MODIFICATION_REQUEST(e1ap_bearer_setup_req_t *con
|
||||
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.pDCP_Reestablishment) {
|
||||
if (j->pdcp_config && j->pdcp_config->pDCP_Reestablishment) {
|
||||
asn1cCallocOne(pDCP_Configuration->pDCP_Reestablishment, E1AP_PDCP_Reestablishment_true);
|
||||
}
|
||||
if (j->numDlUpParam > 0) {
|
||||
@@ -484,8 +499,8 @@ static int fill_BEARER_CONTEXT_MODIFICATION_REQUEST(e1ap_bearer_setup_req_t *con
|
||||
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->tlAddress, &gTPTunnel->transportLayerAddress);
|
||||
INT32_TO_OCTET_STRING(k->teId, &gTPTunnel->gTP_TEID);
|
||||
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;
|
||||
}
|
||||
@@ -493,7 +508,7 @@ static int fill_BEARER_CONTEXT_MODIFICATION_REQUEST(e1ap_bearer_setup_req_t *con
|
||||
}
|
||||
}
|
||||
/* c4. E1AP_ProtocolIE_ID_id_BearerContextStatusChange */
|
||||
if (bearerCxt->bearerContextStatus == BEARER_SUSPEND) {
|
||||
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;
|
||||
@@ -608,6 +623,26 @@ static void extract_BEARER_CONTEXT_MODIFICATION_REQUEST(const E1AP_E1AP_PDU_t *p
|
||||
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);
|
||||
@@ -637,7 +672,8 @@ static void extract_BEARER_CONTEXT_MODIFICATION_REQUEST(const E1AP_E1AP_PDU_t *p
|
||||
if (drb2Mod->pDCP_Configuration != NULL
|
||||
&& drb2Mod->pDCP_Configuration->pDCP_Reestablishment != NULL
|
||||
&& *drb2Mod->pDCP_Configuration->pDCP_Reestablishment == E1AP_PDCP_Reestablishment_true) {
|
||||
drb->pdcp_config.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;
|
||||
@@ -649,8 +685,8 @@ static void extract_BEARER_CONTEXT_MODIFICATION_REQUEST(const E1AP_E1AP_PDU_t *p
|
||||
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->tlAddress);
|
||||
OCTET_STRING_TO_INT32(&dl_up_param_in->uP_TNL_Information.choice.gTPTunnel->gTP_TEID, dl_up_param->teId);
|
||||
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");
|
||||
}
|
||||
@@ -665,7 +701,8 @@ static void extract_BEARER_CONTEXT_MODIFICATION_REQUEST(const E1AP_E1AP_PDU_t *p
|
||||
/* Bearer Context Status Change */
|
||||
DevAssert(ie->criticality == E1AP_Criticality_reject);
|
||||
DevAssert(ie->value.present == E1AP_BearerContextModificationRequestIEs__value_PR_BearerContextStatusChange);
|
||||
bearerCxt->bearerContextStatus = (ie->value.choice.BearerContextStatusChange == E1AP_BearerContextStatusChange_suspend) ? BEARER_SUSPEND : BEARER_ACTIVE;
|
||||
bearerCxt->bearerContextStatus = malloc_or_fail(*bearerCxt->bearerContextStatus);
|
||||
*bearerCxt->bearerContextStatus = (ie->value.choice.BearerContextStatusChange == E1AP_BearerContextStatusChange_suspend) ? BEARER_SUSPEND : BEARER_ACTIVE;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -1131,7 +1168,7 @@ static void e1_task_handle_sctp_association_resp(E1_t type,
|
||||
if (getCxtE1(instance)->gtpInstF1U < 0)
|
||||
getCxtE1(instance)->gtpInstF1U = cuup_task_create_gtpu_instance_to_du(&IPaddr);
|
||||
if (getCxtE1(instance)->gtpInstF1U < 0)
|
||||
LOG_E(E1AP, "Failed to create CUUP F1-U UDP listener");
|
||||
LOG_E(E1AP, "Failed to create CUUP F1-U UDP listener\n");
|
||||
extern instance_t CUuniqInstance;
|
||||
CUuniqInstance = getCxtE1(instance)->gtpInstF1U;
|
||||
cuup_init_n3(instance);
|
||||
@@ -1154,7 +1191,7 @@ void cuup_init_n3(instance_t instance)
|
||||
legacyInstanceMapping = getCxtE1(instance)->gtpInstN3 = gtpv1Init(tmp);
|
||||
}
|
||||
if (getCxtE1(instance)->gtpInstN3 < 0)
|
||||
LOG_E(E1AP, "Failed to create CUUP N3 UDP listener");
|
||||
LOG_E(E1AP, "Failed to create CUUP N3 UDP listener\n");
|
||||
extern instance_t *N3GTPUInst;
|
||||
N3GTPUInst = &getCxtE1(instance)->gtpInstN3;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
add_library(e1ap_lib OBJECT
|
||||
e1ap_bearer_context_management.c
|
||||
e1ap_interface_management.c
|
||||
e1ap_lib_common.c
|
||||
)
|
||||
|
||||
target_link_libraries(e1ap_lib PRIVATE asn1_e1ap)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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_ */
|
||||
|
||||
@@ -508,61 +508,6 @@ bool eq_e1ap_cuup_setup_response(const e1ap_setup_resp_t *a, const e1ap_setup_re
|
||||
* GNB-CU-UP E1 SETUP FAILURE
|
||||
* ==================================== */
|
||||
|
||||
static E1AP_Cause_t encode_e1ap_cause_ie(const e1ap_cause_t *cause)
|
||||
{
|
||||
E1AP_Cause_t ie;
|
||||
switch (cause->type) {
|
||||
case E1AP_CAUSE_RADIO_NETWORK:
|
||||
ie.present = E1AP_Cause_PR_radioNetwork;
|
||||
ie.choice.radioNetwork = cause->value;
|
||||
break;
|
||||
case E1AP_CAUSE_TRANSPORT:
|
||||
ie.present = E1AP_Cause_PR_transport;
|
||||
ie.choice.transport = cause->value;
|
||||
break;
|
||||
case E1AP_CAUSE_PROTOCOL:
|
||||
ie.present = E1AP_Cause_PR_protocol;
|
||||
ie.choice.protocol = cause->value;
|
||||
break;
|
||||
case E1AP_CAUSE_MISC:
|
||||
ie.present = E1AP_Cause_PR_misc;
|
||||
ie.choice.misc = cause->value;
|
||||
break;
|
||||
default:
|
||||
ie.present = E1AP_Cause_PR_NOTHING;
|
||||
break;
|
||||
}
|
||||
return ie;
|
||||
}
|
||||
|
||||
static e1ap_cause_t decode_e1ap_cause_ie(const E1AP_Cause_t *ie)
|
||||
{
|
||||
e1ap_cause_t cause;
|
||||
// Decode the 'choice' field based on the 'present' value
|
||||
switch (ie->present) {
|
||||
case E1AP_Cause_PR_radioNetwork:
|
||||
cause.value = ie->choice.radioNetwork;
|
||||
cause.type = E1AP_CAUSE_RADIO_NETWORK;
|
||||
break;
|
||||
case E1AP_Cause_PR_transport:
|
||||
cause.value = ie->choice.transport;
|
||||
cause.type = E1AP_CAUSE_TRANSPORT;
|
||||
break;
|
||||
case E1AP_Cause_PR_protocol:
|
||||
cause.value = ie->choice.protocol;
|
||||
cause.type = E1AP_CAUSE_PROTOCOL;
|
||||
break;
|
||||
case E1AP_Cause_PR_misc:
|
||||
cause.value = ie->choice.misc;
|
||||
cause.type = E1AP_CAUSE_MISC;
|
||||
break;
|
||||
default:
|
||||
cause.type = E1AP_CAUSE_NOTHING;
|
||||
break;
|
||||
}
|
||||
return cause;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Encoder for GNB-CU-UP E1 Setup Failure
|
||||
* @ref 9.2.1.6 GNB-CU-UP E1 SETUP FAILURE of 3GPP TS 38.463
|
||||
@@ -588,7 +533,7 @@ E1AP_E1AP_PDU_t *encode_e1ap_cuup_setup_failure(const e1ap_setup_fail_t *msg)
|
||||
ie2->id = E1AP_ProtocolIE_ID_id_Cause;
|
||||
ie2->criticality = E1AP_Criticality_ignore;
|
||||
ie2->value.present = E1AP_GNB_CU_UP_E1SetupFailureIEs__value_PR_Cause;
|
||||
ie2->value.choice.Cause = encode_e1ap_cause_ie(&msg->cause);
|
||||
ie2->value.choice.Cause = e1_encode_cause_ie(&msg->cause);
|
||||
// Time To Wait (O)
|
||||
if (msg->time_to_wait) {
|
||||
asn1cSequenceAdd(out->protocolIEs.list, E1AP_GNB_CU_UP_E1SetupFailureIEs_t, ie3);
|
||||
@@ -630,7 +575,7 @@ bool decode_e1ap_cuup_setup_failure(const E1AP_E1AP_PDU_t *pdu, e1ap_setup_fail_
|
||||
case E1AP_ProtocolIE_ID_id_Cause:
|
||||
// Cause
|
||||
E1AP_LIB_FIND_IE(E1AP_GNB_CU_UP_E1SetupFailureIEs_t, ie, in, E1AP_ProtocolIE_ID_id_Cause, true);
|
||||
out->cause = decode_e1ap_cause_ie(&ie->value.choice.Cause);
|
||||
out->cause = e1_decode_cause_ie(&ie->value.choice.Cause);
|
||||
break;
|
||||
case E1AP_ProtocolIE_ID_id_Transport_Layer_Address_Info:
|
||||
// Time To Wait (O)
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#include "e1ap_lib_common.h"
|
||||
#include "e1ap_lib_includes.h"
|
||||
#include "e1ap_messages_types.h"
|
||||
|
||||
E1AP_Cause_t e1_encode_cause_ie(const e1ap_cause_t *cause)
|
||||
{
|
||||
E1AP_Cause_t ie;
|
||||
switch (cause->type) {
|
||||
case E1AP_CAUSE_RADIO_NETWORK:
|
||||
ie.present = E1AP_Cause_PR_radioNetwork;
|
||||
ie.choice.radioNetwork = cause->value;
|
||||
break;
|
||||
case E1AP_CAUSE_TRANSPORT:
|
||||
ie.present = E1AP_Cause_PR_transport;
|
||||
ie.choice.transport = cause->value;
|
||||
break;
|
||||
case E1AP_CAUSE_PROTOCOL:
|
||||
ie.present = E1AP_Cause_PR_protocol;
|
||||
ie.choice.protocol = cause->value;
|
||||
break;
|
||||
case E1AP_CAUSE_MISC:
|
||||
ie.present = E1AP_Cause_PR_misc;
|
||||
ie.choice.misc = cause->value;
|
||||
break;
|
||||
default:
|
||||
ie.present = E1AP_Cause_PR_NOTHING;
|
||||
PRINT_ERROR("encode_e1ap_cause_ie: no cause value provided\n");
|
||||
break;
|
||||
}
|
||||
return ie;
|
||||
}
|
||||
|
||||
e1ap_cause_t e1_decode_cause_ie(const E1AP_Cause_t *ie)
|
||||
{
|
||||
e1ap_cause_t cause;
|
||||
// Decode the 'choice' field based on the 'present' value
|
||||
switch (ie->present) {
|
||||
case E1AP_Cause_PR_radioNetwork:
|
||||
cause.value = ie->choice.radioNetwork;
|
||||
cause.type = E1AP_CAUSE_RADIO_NETWORK;
|
||||
break;
|
||||
case E1AP_Cause_PR_transport:
|
||||
cause.value = ie->choice.transport;
|
||||
cause.type = E1AP_CAUSE_TRANSPORT;
|
||||
break;
|
||||
case E1AP_Cause_PR_protocol:
|
||||
cause.value = ie->choice.protocol;
|
||||
cause.type = E1AP_CAUSE_PROTOCOL;
|
||||
break;
|
||||
case E1AP_Cause_PR_misc:
|
||||
cause.value = ie->choice.misc;
|
||||
cause.type = E1AP_CAUSE_MISC;
|
||||
break;
|
||||
default:
|
||||
cause.type = E1AP_CAUSE_NOTHING;
|
||||
PRINT_ERROR("decode_e1ap_cause_ie: no cause value provided\n");
|
||||
break;
|
||||
}
|
||||
return cause;
|
||||
}
|
||||
@@ -26,13 +26,22 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include "openair3/UTILS/conversions.h"
|
||||
#include "e1ap_messages_types.h"
|
||||
|
||||
#ifdef ENABLE_TESTS
|
||||
#ifdef E1AP_LOG_ERRORS
|
||||
#define PRINT_ERROR(...) fprintf(stderr, ##__VA_ARGS__);
|
||||
#else
|
||||
#define PRINT_ERROR(...) // Do nothing
|
||||
#endif
|
||||
|
||||
#define CHECK_E1AP_DEC(exp) \
|
||||
do { \
|
||||
if (!(exp)) { \
|
||||
PRINT_ERROR("Failed executing " #exp " in %s() line %d\n", __func__, __LINE__); \
|
||||
return false; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define _E1_EQ_CHECK_GENERIC(condition, fmt, ...) \
|
||||
do { \
|
||||
if (!(condition)) { \
|
||||
@@ -66,4 +75,40 @@
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* deep copy of optional E1AP IE */
|
||||
#define _E1_CP_OPTIONAL_IE(dest, src, field) \
|
||||
do { \
|
||||
if ((src)->field) { \
|
||||
(dest)->field = malloc_or_fail(sizeof(*(dest)->field)); \
|
||||
*(dest)->field = *(src)->field; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define _E1_EQ_CHECK_OPTIONAL_IE(a, b, field, EQ_MACRO) \
|
||||
do { \
|
||||
if (((a)->field && !(b)->field) || (!(a)->field && (b)->field)) { \
|
||||
return false; /* One of the two is not allocated */ \
|
||||
} \
|
||||
if ((a)->field && (b)->field) { \
|
||||
EQ_MACRO(*(a)->field, *(b)->field) \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define _E1_EQ_CHECK_OPTIONAL_PTR(a, b, field) \
|
||||
do { \
|
||||
if (((a)->field && !(b)->field) || (!(a)->field && (b)->field)) { \
|
||||
PRINT_ERROR("%s:%d: optional IE '%s' not allocated: %p, %p\n", \
|
||||
__FILE__, \
|
||||
__LINE__, \
|
||||
#field, \
|
||||
(void *)(a)->field, \
|
||||
(void *)(b)->field); \
|
||||
return false; /* One of the two is not allocated */ \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
struct E1AP_Cause;
|
||||
struct E1AP_Cause e1_encode_cause_ie(const e1ap_cause_t *cause);
|
||||
e1ap_cause_t e1_decode_cause_ie(const struct E1AP_Cause *ie);
|
||||
|
||||
#endif /* E1AP_LIB_COMMON_H_ */
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
#include "E1AP_System-BearerContextSetupRequest.h"
|
||||
#include "E1AP_MaximumIPdatarate.h"
|
||||
#include "E1AP_PDU-Session-Type.h"
|
||||
#include "E1AP_Data-Forwarding-Information.h"
|
||||
// E1 Bearer Context Setup Response
|
||||
#include "E1AP_PDU-Session-Resource-Setup-Item.h"
|
||||
#include "E1AP_DRB-Setup-Item-NG-RAN.h"
|
||||
@@ -66,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_ */
|
||||
|
||||
@@ -70,6 +70,14 @@ static void e1ap_msg_free(E1AP_E1AP_PDU_t *pdu)
|
||||
ASN_STRUCT_FREE(asn_DEF_E1AP_E1AP_PDU, pdu);
|
||||
}
|
||||
|
||||
static UP_TL_information_t create_up_tl_info(void)
|
||||
{
|
||||
UP_TL_information_t tl_info;
|
||||
tl_info.tlAddress = htonl(0xC0A90001); // 192.169.0.1
|
||||
tl_info.teId = 0x2345;
|
||||
return tl_info;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Test E1AP Bearer Context Setup Request encoding/decoding
|
||||
*/
|
||||
@@ -77,7 +85,7 @@ static void test_bearer_context_setup_request(void)
|
||||
{
|
||||
bearer_context_pdcp_config_t pdcp = {
|
||||
.discardTimer = E1AP_DiscardTimer_ms10,
|
||||
.pDCP_Reestablishment = E1AP_PDCP_Reestablishment_true,
|
||||
.pDCP_Reestablishment = true,
|
||||
.pDCP_SN_Size_DL = E1AP_PDCP_SN_Size_s_12,
|
||||
.pDCP_SN_Size_UL = E1AP_PDCP_SN_Size_s_12,
|
||||
.reorderingTimer = 10,
|
||||
@@ -107,14 +115,13 @@ static void test_bearer_context_setup_request(void)
|
||||
// Step 1: Initialize the E1AP Bearer Context Setup Request
|
||||
e1ap_bearer_setup_req_t orig = {
|
||||
.gNB_cu_cp_ue_id = 1234,
|
||||
.cipheringAlgorithm = 0x01,
|
||||
.integrityProtectionAlgorithm = 0x01,
|
||||
.secInfo.cipheringAlgorithm = 0x01,
|
||||
.secInfo.integrityProtectionAlgorithm = 0x01,
|
||||
.ueDlAggMaxBitRate = 1000000000,
|
||||
.bearerContextStatus = 0,
|
||||
.servingPLMNid.mcc = 001,
|
||||
.servingPLMNid.mnc = 01,
|
||||
.servingPLMNid.mnc_digit_length = 0x02,
|
||||
.activityNotificationLevel = ANL_PDU_SESSION,
|
||||
.numPDUSessions = 1,
|
||||
.pduSession[0].sessionId = 1,
|
||||
.pduSession[0].sessionType = E1AP_PDU_Session_Type_ipv4,
|
||||
@@ -122,8 +129,7 @@ static void test_bearer_context_setup_request(void)
|
||||
.pduSession[0].nssai.sst = 0x01,
|
||||
.pduSession[0].securityIndication = security,
|
||||
.pduSession[0].numDRB2Setup = 1,
|
||||
.pduSession[0].UP_TL_information.tlAddress = 167772161,
|
||||
.pduSession[0].UP_TL_information.teId = 0x12345,
|
||||
.pduSession[0].UP_TL_information = create_up_tl_info(),
|
||||
.pduSession[0].DRBnGRanList[0].id = 1,
|
||||
.pduSession[0].DRBnGRanList[0].sdap_config = sdap,
|
||||
.pduSession[0].DRBnGRanList[0].pdcp_config = pdcp,
|
||||
@@ -133,8 +139,8 @@ static void test_bearer_context_setup_request(void)
|
||||
.pduSession[0].DRBnGRanList[0].numQosFlow2Setup = 1,
|
||||
.pduSession[0].DRBnGRanList[0].qosFlows[0] = qos,
|
||||
};
|
||||
memset(orig.encryptionKey, 0xAB, sizeof(orig.encryptionKey));
|
||||
memset(orig.integrityProtectionKey, 0xCD, sizeof(orig.integrityProtectionKey));
|
||||
memset(orig.secInfo.encryptionKey, 0xAB, sizeof(orig.secInfo.encryptionKey));
|
||||
memset(orig.secInfo.integrityProtectionKey, 0xCD, sizeof(orig.secInfo.integrityProtectionKey));
|
||||
// E1AP encode the original message
|
||||
E1AP_E1AP_PDU_t *enc = encode_E1_bearer_context_setup_request(&orig);
|
||||
// E1AP decode the encoded message
|
||||
@@ -172,8 +178,7 @@ static void test_bearer_context_setup_response(void)
|
||||
.gNB_cu_up_ue_id = 5678,
|
||||
.numPDUSessions = 1,
|
||||
.pduSession[0].id = 1,
|
||||
.pduSession[0].tlAddress = 167772161,
|
||||
.pduSession[0].teId = 0x12345,
|
||||
.pduSession[0].tl_info = create_up_tl_info(),
|
||||
.pduSession[0].numDRBSetup = 1,
|
||||
.pduSession[0].numDRBFailed = 0,
|
||||
.pduSession[0].DRBnGRanList[0].id = 1,
|
||||
@@ -181,8 +186,7 @@ static void test_bearer_context_setup_response(void)
|
||||
.pduSession[0].DRBnGRanList[0].numQosFlowSetup = 1,
|
||||
.pduSession[0].DRBnGRanList[0].qosFlows[0].qfi = 1,
|
||||
.pduSession[0].DRBnGRanList[0].UpParamList[0].cell_group_id = MCG,
|
||||
.pduSession[0].DRBnGRanList[0].UpParamList[0].teId = 0x34345,
|
||||
.pduSession[0].DRBnGRanList[0].UpParamList[0].tlAddress = 167772161,
|
||||
.pduSession[0].DRBnGRanList[0].UpParamList[0].tl_info = create_up_tl_info(),
|
||||
};
|
||||
// E1AP encode the original message
|
||||
E1AP_E1AP_PDU_t *enc = encode_E1_bearer_context_setup_response(&orig);
|
||||
@@ -335,6 +339,120 @@ static void test_e1_cuup_setup_failure(void)
|
||||
free_e1ap_cuup_setup_failure(&orig);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Test E1AP Bearer Context Modification Request encoding/decoding
|
||||
*/
|
||||
static void test_bearer_context_modification_request(void)
|
||||
{
|
||||
const bearer_context_sdap_config_t dummy_sdap_config = {
|
||||
.defaultDRB = 0,
|
||||
.sDAP_Header_DL = false,
|
||||
.sDAP_Header_UL = false,
|
||||
};
|
||||
|
||||
const bearer_context_pdcp_config_t dummy_pdcp_config = {
|
||||
.discardTimer = E1AP_DiscardTimer_ms100,
|
||||
.pDCP_Reestablishment = true,
|
||||
.pDCP_SN_Size_DL = E1AP_PDCP_SN_Size_s_12,
|
||||
.pDCP_SN_Size_UL = E1AP_PDCP_SN_Size_s_12,
|
||||
.reorderingTimer = 5,
|
||||
.rLC_Mode = E1AP_RLC_Mode_rlc_um_bidirectional,
|
||||
};
|
||||
|
||||
const qos_flow_to_setup_t dummy_qos_flows = {
|
||||
.qfi = 9,
|
||||
.qos_params.alloc_reten_priority.preemption_capability = E1AP_Pre_emptionCapability_may_trigger_pre_emption,
|
||||
.qos_params.alloc_reten_priority.preemption_vulnerability = E1AP_Pre_emptionVulnerability_pre_emptable,
|
||||
.qos_params.alloc_reten_priority.priority_level = E1AP_PriorityLevel_no_priority,
|
||||
.qos_params.qos_characteristics.non_dynamic.fiveqi = 9,
|
||||
};
|
||||
|
||||
DRB_nGRAN_to_mod_t drb_to_mod = {
|
||||
.numDlUpParam = 1,
|
||||
.DlUpParamList[0].cell_group_id = MCG,
|
||||
.DlUpParamList[0].tl_info = create_up_tl_info(),
|
||||
.id = 1,
|
||||
.pdcp_config = malloc_or_fail(sizeof(*drb_to_mod.pdcp_config)),
|
||||
.pdcp_sn_status_requested = true,
|
||||
.numQosFlow2Setup = 1,
|
||||
.qosFlows[0] = dummy_qos_flows,
|
||||
};
|
||||
*drb_to_mod.pdcp_config = dummy_pdcp_config;
|
||||
|
||||
pdu_session_to_mod_t pdusession_mod_item = {
|
||||
.sessionId = 1,
|
||||
.numDRB2Modify = 1,
|
||||
.DRBnGRanModList[0] = drb_to_mod,
|
||||
};
|
||||
|
||||
DRB_nGRAN_to_setup_t drb_to_setup = {
|
||||
.id = 1,
|
||||
.cellGroupList[0] = MCG,
|
||||
.numCellGroups = 1,
|
||||
.pdcp_config = dummy_pdcp_config,
|
||||
.sdap_config = dummy_sdap_config,
|
||||
.numQosFlow2Setup = 1,
|
||||
.qosFlows[0] = dummy_qos_flows,
|
||||
.drb_inactivity_timer = malloc_or_fail(sizeof(*drb_to_setup.drb_inactivity_timer)),
|
||||
};
|
||||
*drb_to_setup.drb_inactivity_timer = 500;
|
||||
|
||||
pdu_session_to_setup_t pdusession_setup_item = {
|
||||
.numDRB2Setup = 1,
|
||||
.nssai.sd = 0x01,
|
||||
.nssai.sst = 0x01,
|
||||
.UP_TL_information.teId = 0x12345,
|
||||
.UP_TL_information.tlAddress = 167772161,
|
||||
.DRBnGRanList[0] = drb_to_setup,
|
||||
};
|
||||
|
||||
// Initialize the Bearer Context Modification Request
|
||||
e1ap_bearer_mod_req_t orig = {
|
||||
.gNB_cu_cp_ue_id = 0x1234,
|
||||
.gNB_cu_up_ue_id = 0x5678,
|
||||
.bearerContextStatus = malloc_or_fail(sizeof(*orig.bearerContextStatus)),
|
||||
.inactivityTimer = malloc_or_fail(sizeof(*orig.inactivityTimer)),
|
||||
.numPDUSessions = 1,
|
||||
.pduSession[0] = pdusession_setup_item,
|
||||
.numPDUSessionsMod = 1,
|
||||
.pduSessionMod[0] = pdusession_mod_item,
|
||||
};
|
||||
*orig.bearerContextStatus = BEARER_SUSPEND;
|
||||
*orig.inactivityTimer = 1000;
|
||||
|
||||
// Encode the original message
|
||||
E1AP_E1AP_PDU_t *enc = encode_E1_bearer_context_mod_request(&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_mod_req_t decoded = {0};
|
||||
AssertFatal(decode_E1_bearer_context_mod_request(dec, &decoded), "decode_E1_bearer_context_mod_request(): could not decode message\n");
|
||||
|
||||
// Free the decoded E1AP message
|
||||
e1ap_msg_free(dec);
|
||||
|
||||
// Compare the original and decoded structs
|
||||
AssertFatal(eq_bearer_context_mod_request(&orig, &decoded), "eq_bearer_context_mod_request(): decoded message doesn't match\n");
|
||||
|
||||
// Free the memory for the decoded message
|
||||
free_e1ap_context_mod_request(&decoded);
|
||||
|
||||
// Deep copy the original message
|
||||
e1ap_bearer_mod_req_t cp = cp_bearer_context_mod_request(&orig);
|
||||
|
||||
// Verify the deep copy matches the original
|
||||
AssertFatal(eq_bearer_context_mod_request(&orig, &cp), "eq_bearer_context_mod_request(): copied message doesn't match\n");
|
||||
|
||||
// Free the copied and original message
|
||||
free_e1ap_context_mod_request(&cp);
|
||||
free_e1ap_context_mod_request(&orig);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
// E1 Bearer Context Setup
|
||||
@@ -344,5 +462,7 @@ int main()
|
||||
test_e1_cuup_setup_request();
|
||||
test_e1_cuup_setup_response();
|
||||
test_e1_cuup_setup_failure();
|
||||
// E1 Bearer Context Modification Request
|
||||
test_bearer_context_modification_request();
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user