Commit 85949411 authored by Robert Schmidt's avatar Robert Schmidt

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.)
parents 805ed557 ac6b1b18
......@@ -9,6 +9,7 @@ services:
environment:
USE_ADDITIONAL_OPTIONS: --telnetsrv --telnetsrv.listenport 9090 --telnetsrv.shrmod ci
--log_config.global_log_options level,nocolor,time,line_num,function
--security.drb_integrity yes
volumes:
- ../../conf_files/gnb-cucp.sa.f1.quectel.conf:/opt/oai-gnb/etc/gnb.conf
# for performance reasons, we use host mode: in bridge mode, we have
......
......@@ -125,7 +125,7 @@ void nr_derive_key_ng_ran_star(uint16_t pci, uint64_t nr_arfcn_dl, const uint8_t
int dummy_nr_ue_ul_indication(nr_uplink_indication_t *ul_info) { return(0); }
void e1_bearer_context_setup(const e1ap_bearer_setup_req_t *req) { abort(); }
void e1_bearer_context_modif(const e1ap_bearer_setup_req_t *req) { abort(); }
void e1_bearer_context_modif(const e1ap_bearer_mod_req_t *req) { abort(); }
void e1_bearer_release_cmd(const e1ap_bearer_release_cmd_t *cmd) { abort(); }
int8_t nr_rrc_RA_succeeded(const module_id_t mod_id, const uint8_t gNB_index) {
......
......@@ -51,7 +51,7 @@ void e1_bearer_context_setup(const e1ap_bearer_setup_req_t *req)
{
abort();
}
void e1_bearer_context_modif(const e1ap_bearer_setup_req_t *req)
void e1_bearer_context_modif(const e1ap_bearer_mod_req_t *req)
{
abort();
}
......
......@@ -126,7 +126,7 @@ void nr_derive_key_ng_ran_star(uint16_t pci, uint64_t nr_arfcn_dl, const uint8_t
extern void fix_scd(NR_ServingCellConfig_t *scd);// forward declaration
void e1_bearer_context_setup(const e1ap_bearer_setup_req_t *req) { abort(); }
void e1_bearer_context_modif(const e1ap_bearer_setup_req_t *req) { abort(); }
void e1_bearer_context_modif(const e1ap_bearer_mod_req_t *req) { abort(); }
void e1_bearer_release_cmd(const e1ap_bearer_release_cmd_t *cmd) { abort(); }
int8_t nr_rrc_RA_succeeded(const module_id_t mod_id, const uint8_t gNB_index) {
......
This diff is collapsed.
......@@ -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()
......@@ -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;
}
......
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)
......
......@@ -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)
......
/*
* 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;
}
......@@ -168,7 +168,6 @@ void e1_bearer_context_setup(const e1ap_bearer_setup_req_t *req)
const pdu_session_to_setup_t *req_pdu = req->pduSession + i;
resp_pdu->id = req_pdu->sessionId;
AssertFatal(req_pdu->numDRB2Modify == 0, "DRB modification not implemented\n");
AssertFatal(req_pdu->numDRB2Setup == 1, "can only handle one DRB per PDU session\n");
resp_pdu->numDRBSetup = req_pdu->numDRB2Setup;
const DRB_nGRAN_to_setup_t *req_drb = &req_pdu->DRBnGRanList[0];
......@@ -178,7 +177,7 @@ void e1_bearer_context_setup(const e1ap_bearer_setup_req_t *req)
resp_drb->numQosFlowSetup = req_drb->numQosFlow2Setup;
for (int k = 0; k < resp_drb->numQosFlowSetup; k++) {
const qos_flow_to_setup_t *qosflow2Setup = &req_drb->qosFlows[k];
qos_flow_setup_t *qosflowSetup = &resp_drb->qosFlows[k];
qos_flow_list_t *qosflowSetup = &resp_drb->qosFlows[k];
qosflowSetup->qfi = qosflow2Setup->qfi;
}
......@@ -197,17 +196,17 @@ void e1_bearer_context_setup(const e1ap_bearer_setup_req_t *req)
&resp_n3);
AssertFatal(ret >= 0, "Unable to create GTP Tunnel for NG-U\n");
AssertFatal(resp_n3.num_tunnels == req_pdu->numDRB2Setup, "could not create all tunnels\n");
resp_pdu->teId = resp_n3.gnb_NGu_teid[0];
memcpy(&resp_pdu->tlAddress, &resp_n3.gnb_addr.buffer, 4);
resp_pdu->tl_info.teId = resp_n3.gnb_NGu_teid[0];
memcpy(&resp_pdu->tl_info.tlAddress, &resp_n3.gnb_addr.buffer, 4);
// create PDCP bearers. This will also create SDAP bearers
NR_DRB_ToAddModList_t DRB_configList = {0};
fill_DRB_configList_e1(&DRB_configList, req_pdu);
nr_pdcp_entity_security_keys_and_algos_t security_parameters;
security_parameters.ciphering_algorithm = req->cipheringAlgorithm;
security_parameters.integrity_algorithm = req->integrityProtectionAlgorithm;
memcpy(security_parameters.ciphering_key, req->encryptionKey, NR_K_KEY_SIZE);
memcpy(security_parameters.integrity_key, req->integrityProtectionKey, NR_K_KEY_SIZE);
security_parameters.ciphering_algorithm = req->secInfo.cipheringAlgorithm;
security_parameters.integrity_algorithm = req->secInfo.integrityProtectionAlgorithm;
memcpy(security_parameters.ciphering_key, req->secInfo.encryptionKey, NR_K_KEY_SIZE);
memcpy(security_parameters.integrity_key, req->secInfo.integrityProtectionKey, NR_K_KEY_SIZE);
nr_pdcp_add_drbs(true, // set this to notify PDCP that his not UE
cu_up_ue_id,
&DRB_configList,
......@@ -230,8 +229,8 @@ void e1_bearer_context_setup(const e1ap_bearer_setup_req_t *req)
&resp_f1);
resp_drb->numUpParam = 1;
AssertFatal(ret >= 0, "Unable to create GTP Tunnel for F1-U\n");
memcpy(&resp_drb->UpParamList[0].tlAddress, &resp_f1.gnb_addr.buffer, 4);
resp_drb->UpParamList[0].teId = resp_f1.gnb_NGu_teid[0];
memcpy(&resp_drb->UpParamList[0].tl_info.tlAddress, &resp_f1.gnb_addr.buffer, 4);
resp_drb->UpParamList[0].tl_info.teId = resp_f1.gnb_NGu_teid[0];
}
// We assume all DRBs to setup have been setup successfully, so we always
......@@ -273,12 +272,18 @@ void e1_bearer_context_modif(const e1ap_bearer_mod_req_t *req)
DRB_nGRAN_modified_t *modified = &modif.pduSessionMod[i].DRBnGRanModList[j];
modified->id = to_modif->id;
if (to_modif->pdcp_config.pDCP_Reestablishment) {
if (to_modif->pdcp_config && to_modif->pdcp_config->pDCP_Reestablishment) {
nr_pdcp_entity_security_keys_and_algos_t security_parameters;
security_parameters.ciphering_algorithm = req->cipheringAlgorithm;
security_parameters.integrity_algorithm = req->integrityProtectionAlgorithm;
memcpy(security_parameters.ciphering_key, req->encryptionKey, NR_K_KEY_SIZE);
memcpy(security_parameters.integrity_key, req->integrityProtectionKey, NR_K_KEY_SIZE);
if (req->secInfo) {
security_parameters.ciphering_algorithm = req->secInfo->cipheringAlgorithm;
security_parameters.integrity_algorithm = req->secInfo->integrityProtectionAlgorithm;
memcpy(security_parameters.ciphering_key, req->secInfo->encryptionKey, NR_K_KEY_SIZE);
memcpy(security_parameters.integrity_key, req->secInfo->integrityProtectionKey, NR_K_KEY_SIZE);
} else {
/* don't change security settings if not present in the Bearer Context Modification Request */
security_parameters.ciphering_algorithm = -1;
security_parameters.integrity_algorithm = -1;
}
nr_pdcp_reestablishment(req->gNB_cu_up_ue_id,
to_modif->id,
false,
......@@ -291,8 +296,8 @@ void e1_bearer_context_modif(const e1ap_bearer_mod_req_t *req)
/* Loop through DL UP Transport Layer params list
* and update GTP tunnel outgoing addr and TEID */
for (int k = 0; k < to_modif->numDlUpParam; k++) {
in_addr_t addr = to_modif->DlUpParamList[k].tlAddress;
GtpuUpdateTunnelOutgoingAddressAndTeid(f1inst, req->gNB_cu_cp_ue_id, to_modif->id, addr, to_modif->DlUpParamList[k].teId);
in_addr_t addr = to_modif->DlUpParamList[k].tl_info.tlAddress;
GtpuUpdateTunnelOutgoingAddressAndTeid(f1inst, req->gNB_cu_cp_ue_id, to_modif->id, addr, to_modif->DlUpParamList[k].tl_info.teId);
}
}
}
......
......@@ -27,9 +27,10 @@
void nr_pdcp_e1_if_init(bool uses_e1);
struct e1ap_bearer_setup_req_s;
struct e1ap_bearer_mod_req_s;
struct e1ap_bearer_release_cmd_s;
void e1_bearer_context_setup(const struct e1ap_bearer_setup_req_s *req);
void e1_bearer_context_modif(const struct e1ap_bearer_setup_req_s *req);
void e1_bearer_context_modif(const struct e1ap_bearer_mod_req_s *req);
void e1_bearer_release_cmd(const struct e1ap_bearer_release_cmd_s *cmd);
void e1_reset(void);
......
......@@ -26,6 +26,7 @@
#include "e1ap_messages_types.h"
#include "intertask_interface.h"
#include "nr_rrc_defs.h"
#include "E1AP/lib/e1ap_bearer_context_management.h"
static void cucp_cuup_bearer_context_setup_e1ap(sctp_assoc_t assoc_id, const e1ap_bearer_setup_req_t *req)
{
......@@ -33,8 +34,7 @@ static void cucp_cuup_bearer_context_setup_e1ap(sctp_assoc_t assoc_id, const e1a
MessageDef *msg_p = itti_alloc_new_message(TASK_CUCP_E1, 0, E1AP_BEARER_CONTEXT_SETUP_REQ);
msg_p->ittiMsgHeader.originInstance = assoc_id;
e1ap_bearer_setup_req_t *bearer_req = &E1AP_BEARER_CONTEXT_SETUP_REQ(msg_p);
memcpy(bearer_req, req, sizeof(e1ap_bearer_setup_req_t));
*bearer_req = cp_bearer_context_setup_request(req);
itti_send_msg_to_task (TASK_CUCP_E1, 0, msg_p);
}
......
......@@ -29,9 +29,11 @@
#include "common/platform_types.h"
struct e1ap_bearer_setup_req_s;
struct e1ap_bearer_mod_req_s;
struct e1ap_bearer_setup_resp_s;
struct e1ap_bearer_release_cmd_s;
typedef void (*cucp_cuup_bearer_context_setup_func_t)(sctp_assoc_t assoc_id, const struct e1ap_bearer_setup_req_s *req);
typedef void (*cucp_cuup_bearer_context_mod_func_t)(sctp_assoc_t assoc_id, const struct e1ap_bearer_mod_req_s *req);
typedef void (*cucp_cuup_bearer_context_release_func_t)(sctp_assoc_t assoc_id, const struct e1ap_bearer_release_cmd_s *cmd);
struct gNB_RRC_INST_s;
......
......@@ -343,7 +343,7 @@ typedef struct nr_mac_rrc_dl_if_s {
typedef struct cucp_cuup_if_s {
cucp_cuup_bearer_context_setup_func_t bearer_context_setup;
cucp_cuup_bearer_context_setup_func_t bearer_context_mod;
cucp_cuup_bearer_context_mod_func_t bearer_context_mod;
cucp_cuup_bearer_context_release_func_t bearer_context_release;
} cucp_cuup_if_t;
......
......@@ -736,6 +736,14 @@ void rrc_gNB_generate_dedicatedRRCReconfiguration_release(gNB_RRC_INST *rrc,
nr_rrc_transfer_protected_rrc_message(rrc, ue_p, DL_SCH_LCID_DCCH, buffer, size);
}
static void fill_security_info(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, security_information_t *secInfo)
{
secInfo->cipheringAlgorithm = rrc->security.do_drb_ciphering ? UE->ciphering_algorithm : 0;
secInfo->integrityProtectionAlgorithm = rrc->security.do_drb_integrity ? UE->integrity_algorithm : 0;
nr_derive_key(UP_ENC_ALG, secInfo->cipheringAlgorithm, UE->kgnb, (uint8_t *)secInfo->encryptionKey);
nr_derive_key(UP_INT_ALG, secInfo->integrityProtectionAlgorithm, UE->kgnb, (uint8_t *)secInfo->integrityProtectionKey);
}
/* \brief find existing PDU session inside E1AP Bearer Modif message, or
* point to new one.
* \param bearer_modif E1AP Bearer Modification Message
......@@ -793,20 +801,27 @@ static void cuup_notify_reestablishment(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue_p)
DRB_nGRAN_to_mod_t *drb_e1 = &pdu_e1->DRBnGRanModList[pdu_e1->numDRB2Modify];
drb_e1->id = drb_id;
drb_e1->numDlUpParam = 1;
memcpy(&drb_e1->DlUpParamList[0].tlAddress, &drb->du_tunnel_config.addr.buffer, sizeof(uint8_t) * 4);
drb_e1->DlUpParamList[0].teId = drb->du_tunnel_config.teid;
memcpy(&drb_e1->DlUpParamList[0].tl_info.tlAddress, &drb->du_tunnel_config.addr.buffer, sizeof(uint8_t) * 4);
drb_e1->DlUpParamList[0].tl_info.teId = drb->du_tunnel_config.teid;
/* PDCP configuration */
bearer_context_pdcp_config_t *pdcp_config = &drb_e1->pdcp_config;
if (!drb_e1->pdcp_config)
drb_e1->pdcp_config = malloc_or_fail(sizeof(*drb_e1->pdcp_config));
bearer_context_pdcp_config_t *pdcp_config = drb_e1->pdcp_config;
set_bearer_context_pdcp_config(pdcp_config, drb, rrc->configuration.um_on_default_drb);
pdcp_config->pDCP_Reestablishment = true;
/* increase DRB to modify counter */
pdu_e1->numDRB2Modify += 1;
}
req.cipheringAlgorithm = rrc->security.do_drb_ciphering ? ue_p->ciphering_algorithm : 0;
req.integrityProtectionAlgorithm = rrc->security.do_drb_integrity ? ue_p->integrity_algorithm : 0;
nr_derive_key(UP_ENC_ALG, req.cipheringAlgorithm, ue_p->kgnb, (uint8_t *)req.encryptionKey);
nr_derive_key(UP_INT_ALG, req.integrityProtectionAlgorithm, ue_p->kgnb, (uint8_t *)req.integrityProtectionKey);
#if 0
/* According to current understanding of E1 specifications, it is not needed
* to send security information because this does not change.
* But let's keep the code here in case it's needed.
*/
// Always send security information
req.secInfo = malloc_or_fail(sizeof(*req.secInfo));
fill_security_info(rrc, ue_p, req.secInfo);
#endif
/* Send E1 Bearer Context Modification Request (3GPP TS 38.463) */
sctp_assoc_t assoc_id = get_existing_cuup_for_ue(rrc, ue_p);
......@@ -1855,12 +1870,12 @@ void rrc_gNB_process_dc_overall_timeout(const module_id_t gnb_mod_idP, x2ap_ENDC
/* \brief fill E1 bearer modification's DRB from F1 DRB
* \param drb_e1 pointer to a DRB inside an E1 bearer modification message
* \param drb_f1 pointer to a DRB inside an F1 UE Ctxt modification Response */
static void fill_e1_bearer_modif(DRB_nGRAN_to_setup_t *drb_e1, const f1ap_drb_to_be_setup_t *drb_f1)
static void fill_e1_bearer_modif(DRB_nGRAN_to_mod_t *drb_e1, const f1ap_drb_to_be_setup_t *drb_f1)
{
drb_e1->id = drb_f1->drb_id;
drb_e1->numDlUpParam = drb_f1->up_dl_tnl_length;
drb_e1->DlUpParamList[0].tlAddress = drb_f1->up_dl_tnl[0].tl_address;
drb_e1->DlUpParamList[0].teId = drb_f1->up_dl_tnl[0].teid;
drb_e1->DlUpParamList[0].tl_info.tlAddress = drb_f1->up_dl_tnl[0].tl_address;
drb_e1->DlUpParamList[0].tl_info.teId = drb_f1->up_dl_tnl[0].teid;
}
/**
......@@ -1892,8 +1907,8 @@ static void store_du_f1u_tunnel(const f1ap_drb_to_be_setup_t *drbs, int n, gNB_R
*/
static void f1u_ul_gtp_update(f1u_tunnel_t *f1u, const up_params_t *p)
{
f1u->teid = p->teId;
memcpy(&f1u->addr.buffer, &p->tlAddress, sizeof(uint8_t) * 4);
f1u->teid = p->tl_info.teId;
memcpy(&f1u->addr.buffer, &p->tl_info.tlAddress, sizeof(uint8_t) * 4);
f1u->addr.length = sizeof(in_addr_t);
}
......@@ -1919,10 +1934,10 @@ static void e1_send_bearer_updates(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, f
LOG_E(RRC, "UE %d: UE Context Modif Response: no PDU session for DRB ID %ld\n", UE->rrc_ue_id, drb_f1->drb_id);
continue;
}
pdu_session_to_setup_t *pdu_e1 = find_or_next_pdu_session(&req, pdu_ue->param.pdusession_id);
pdu_session_to_mod_t *pdu_e1 = find_or_next_pdu_session(&req, pdu_ue->param.pdusession_id);
DevAssert(pdu_e1 != NULL);
pdu_e1->sessionId = pdu_ue->param.pdusession_id;
DRB_nGRAN_to_setup_t *drb_e1 = &pdu_e1->DRBnGRanModList[pdu_e1->numDRB2Modify];
DRB_nGRAN_to_mod_t *drb_e1 = &pdu_e1->DRBnGRanModList[pdu_e1->numDRB2Modify];
/* Fill E1 bearer context modification */
fill_e1_bearer_modif(drb_e1, drb_f1);
pdu_e1->numDRB2Modify += 1;
......@@ -1930,10 +1945,9 @@ static void e1_send_bearer_updates(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, f
DevAssert(req.numPDUSessionsMod > 0);
DevAssert(req.numPDUSessions == 0);
req.cipheringAlgorithm = rrc->security.do_drb_ciphering ? UE->ciphering_algorithm : 0;
req.integrityProtectionAlgorithm = rrc->security.do_drb_integrity ? UE->integrity_algorithm : 0;
nr_derive_key(UP_ENC_ALG, req.cipheringAlgorithm, UE->kgnb, (uint8_t *)req.encryptionKey);
nr_derive_key(UP_INT_ALG, req.integrityProtectionAlgorithm, UE->kgnb, (uint8_t *)req.integrityProtectionKey);
// Always send security information
req.secInfo = malloc_or_fail(sizeof(*req.secInfo));
fill_security_info(rrc, UE, req.secInfo);
// send the E1 bearer modification request message to update F1-U tunnel info
sctp_assoc_t assoc_id = get_existing_cuup_for_ue(rrc, UE);
......@@ -2270,9 +2284,9 @@ static int fill_drb_to_be_setup_from_e1_resp(const gNB_RRC_INST *rrc,
f1ap_drb_to_be_setup_t *drb = &drbs[nb_drb];
drb->drb_id = pduSession[p].DRBnGRanList[i].id;
drb->rlc_mode = rrc->configuration.um_on_default_drb ? F1AP_RLC_MODE_UM_BIDIR : F1AP_RLC_MODE_AM;
drb->up_ul_tnl[0].tl_address = drb_config->UpParamList[0].tlAddress;
drb->up_ul_tnl[0].tl_address = drb_config->UpParamList[0].tl_info.tlAddress;
drb->up_ul_tnl[0].port = rrc->eth_params_s.my_portd;
drb->up_ul_tnl[0].teid = drb_config->UpParamList[0].teId;
drb->up_ul_tnl[0].teid = drb_config->UpParamList[0].tl_info.teId;
drb->up_ul_tnl_length = 1;
/* pass QoS info to MAC */
......@@ -2323,8 +2337,8 @@ void rrc_gNB_process_e1_bearer_context_setup_resp(e1ap_bearer_setup_resp_t *resp
LOG_W(RRC, "E1: received setup for PDU session %ld, but has not been requested\n", e1_pdu->id);
continue;
}
rrc_pdu->param.gNB_teid_N3 = e1_pdu->teId;
memcpy(&rrc_pdu->param.gNB_addr_N3.buffer, &e1_pdu->tlAddress, sizeof(uint8_t) * 4);
rrc_pdu->param.gNB_teid_N3 = e1_pdu->tl_info.teId;
memcpy(&rrc_pdu->param.gNB_addr_N3.buffer, &e1_pdu->tl_info.tlAddress, sizeof(uint8_t) * 4);
rrc_pdu->param.gNB_addr_N3.length = sizeof(in_addr_t);
// save the tunnel address for the DRBs
......
......@@ -353,10 +353,11 @@ bool trigger_bearer_setup(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, pdusession
session->nssai = sessions[i].nssai;
decodePDUSessionResourceSetup(session);
bearer_req.gNB_cu_cp_ue_id = UE->rrc_ue_id;
bearer_req.cipheringAlgorithm = UE->ciphering_algorithm;
bearer_req.integrityProtectionAlgorithm = UE->integrity_algorithm;
nr_derive_key(UP_ENC_ALG, UE->ciphering_algorithm, UE->kgnb, (uint8_t *)bearer_req.encryptionKey);
nr_derive_key(UP_INT_ALG, UE->integrity_algorithm, UE->kgnb, (uint8_t *)bearer_req.integrityProtectionKey);
security_information_t *secInfo = &bearer_req.secInfo;
secInfo->cipheringAlgorithm = rrc->security.do_drb_ciphering ? UE->ciphering_algorithm : 0;
secInfo->integrityProtectionAlgorithm = rrc->security.do_drb_integrity ? UE->integrity_algorithm : 0;
nr_derive_key(UP_ENC_ALG, secInfo->cipheringAlgorithm, UE->kgnb, (uint8_t *)secInfo->encryptionKey);
nr_derive_key(UP_INT_ALG, secInfo->integrityProtectionAlgorithm, UE->kgnb, (uint8_t *)secInfo->integrityProtectionKey);
bearer_req.ueDlAggMaxBitRate = ueAggMaxBitRateDownlink;
pdu_session_to_setup_t *pdu = bearer_req.pduSession + bearer_req.numPDUSessions;
bearer_req.numPDUSessions++;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment