From ea0185f84e2e2a2f327f6b3e43a6aaca93f8c685 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Tue, 23 Jan 2024 16:26:33 +0100 Subject: [PATCH 01/10] Introduced define for uint8_t integrity and ciphering keys data structures - the goal is to improve maintanability --- openair2/RRC/NR/nr_rrc_common.h | 1 + openair2/RRC/NR/rrc_gNB.c | 12 ++++++------ openair2/RRC/NR/rrc_gNB_NGAP.c | 6 +++--- openair2/RRC/NR/rrc_gNB_nsa.c | 4 ++-- openair2/RRC/NR_UE/rrc_UE.c | 10 +++++----- 5 files changed, 17 insertions(+), 16 deletions(-) diff --git a/openair2/RRC/NR/nr_rrc_common.h b/openair2/RRC/NR/nr_rrc_common.h index 69dbb9ff0f..f821d842b6 100644 --- a/openair2/RRC/NR/nr_rrc_common.h +++ b/openair2/RRC/NR/nr_rrc_common.h @@ -29,6 +29,7 @@ #define NR_RRC_HEADER_SIZE_MAX 64 #define NR_RRC_BUFFER_SIZE_MAX 1024 #define NR_NUM_SRB 4 +#define NR_K_KEY_SIZE 16 /* K keys have 128 bits length */ typedef struct { char Payload[NR_RRC_BUFFER_SIZE_MAX]; diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 660a427d30..e85eef0685 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -408,8 +408,8 @@ static void activate_srb(gNB_RRC_UE_t *UE, int srb_id) if (srb_id == 1) { nr_pdcp_add_srbs(true, UE->rrc_ue_id, list, 0, NULL, NULL); } else { - uint8_t kRRCenc[16] = {0}; - uint8_t kRRCint[16] = {0}; + uint8_t kRRCenc[NR_K_KEY_SIZE] = {0}; + uint8_t kRRCint[NR_K_KEY_SIZE] = {0}; nr_derive_key(RRC_ENC_ALG, UE->ciphering_algorithm, UE->kgnb, kRRCenc); nr_derive_key(RRC_INT_ALG, UE->integrity_algorithm, UE->kgnb, kRRCint); @@ -904,13 +904,13 @@ static void rrc_gNB_generate_RRCReestablishment(rrc_gNB_ue_context_t *ue_context LOG_I(NR_RRC, "[RAPROC] UE %04x Logical Channel DL-DCCH, Generating NR_RRCReestablishment (bytes %d)\n", ue_p->rnti, size); - uint8_t kRRCenc[16] = {0}; - uint8_t kRRCint[16] = {0}; - uint8_t kUPenc[16] = {0}; + /* Ciphering and Integrity according to TS 33.501 */ + uint8_t kRRCenc[NR_K_KEY_SIZE] = {0}; + uint8_t kRRCint[NR_K_KEY_SIZE] = {0}; + uint8_t kUPenc[NR_K_KEY_SIZE] = {0}; /* Derive the keys from kgnb */ if (ue_p->Srb[1].Active) nr_derive_key(UP_ENC_ALG, ue_p->ciphering_algorithm, ue_p->kgnb, kUPenc); - nr_derive_key(RRC_ENC_ALG, ue_p->ciphering_algorithm, ue_p->kgnb, kRRCenc); nr_derive_key(RRC_INT_ALG, ue_p->integrity_algorithm, ue_p->kgnb, kRRCint); diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index fbd232b1d4..37cc52a007 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -130,9 +130,9 @@ nr_rrc_pdcp_config_security( ) //------------------------------------------------------------------------------ { - uint8_t kRRCenc[16] = {0}; - uint8_t kRRCint[16] = {0}; - uint8_t kUPenc[16] = {0}; + uint8_t kRRCenc[NR_K_KEY_SIZE] = {0}; + uint8_t kRRCint[NR_K_KEY_SIZE] = {0}; + uint8_t kUPenc[NR_K_KEY_SIZE] = {0}; //uint8_t *k_kdf = NULL; static int print_keys= 1; gNB_RRC_UE_t *UE = &ue_context_pP->ue_context; diff --git a/openair2/RRC/NR/rrc_gNB_nsa.c b/openair2/RRC/NR/rrc_gNB_nsa.c index 448de0eb95..f48ad83083 100644 --- a/openair2/RRC/NR/rrc_gNB_nsa.c +++ b/openair2/RRC/NR/rrc_gNB_nsa.c @@ -126,8 +126,8 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context_p, x2a gtpv1u_enb_create_tunnel_req_t create_tunnel_req; gtpv1u_enb_create_tunnel_resp_t create_tunnel_resp; protocol_ctxt_t ctxt={0}; - uint8_t kUPenc[16] = {0}; - uint8_t kUPint[16] = {0}; + uint8_t kUPenc[NR_K_KEY_SIZE] = {0}; + uint8_t kUPint[NR_K_KEY_SIZE] = {0}; int i; gNB_RRC_UE_t *UE = &ue_context_p->ue_context; diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 8385236ff1..401149d8e8 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -987,9 +987,9 @@ static void nr_rrc_ue_process_securityModeCommand(NR_UE_RRC_INST_t *ue_rrc, c1->present = NR_UL_DCCH_MessageType__c1_PR_securityModeComplete; } - uint8_t kRRCenc[16] = {0}; - uint8_t kUPenc[16] = {0}; - uint8_t kRRCint[16] = {0}; + uint8_t kRRCenc[NR_K_KEY_SIZE] = {0}; + uint8_t kUPenc[NR_K_KEY_SIZE] = {0}; + uint8_t kRRCint[NR_K_KEY_SIZE] = {0}; nr_derive_key(UP_ENC_ALG, ue_rrc->cipheringAlgorithm, ue_rrc->kgnb, kUPenc); nr_derive_key(RRC_ENC_ALG, ue_rrc->cipheringAlgorithm, ue_rrc->kgnb, kRRCenc); nr_derive_key(RRC_INT_ALG, ue_rrc->integrityProtAlgorithm, ue_rrc->kgnb, kRRCint); @@ -1167,8 +1167,8 @@ static void nr_rrc_ue_process_RadioBearerConfig(NR_UE_RRC_INST_t *ue_rrc, if (radioBearerConfig->srb3_ToRelease) nr_pdcp_release_srb(ue_rrc->ue_id, 3); - uint8_t kRRCenc[16] = {0}; - uint8_t kRRCint[16] = {0}; + uint8_t kRRCenc[NR_K_KEY_SIZE] = {0}; + uint8_t kRRCint[NR_K_KEY_SIZE] = {0}; if (ue_rrc->as_security_activated) { if (radioBearerConfig->securityConfig != NULL) { // When the field is not included, continue to use the currently configured keyToUse From f392158c40ab6c25e6b107ead152c65291349da9 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Tue, 23 Jan 2024 16:07:21 +0100 Subject: [PATCH 02/10] Removed redundant definition for max SRBs number (used in RRC procedures) - according to specs, in NR there are 4 SRBs - in OAI the relevant define is used in the RRC procedures - this commit harmonizes code by removing redundancy --- common/ngran_types.h | 1 - openair2/RRC/NR/nr_rrc_common.h | 2 +- openair2/RRC/NR/nr_rrc_defs.h | 2 +- openair2/RRC/NR/rrc_gNB.c | 5 +++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/common/ngran_types.h b/common/ngran_types.h index 95ad167961..37a6ea9177 100644 --- a/common/ngran_types.h +++ b/common/ngran_types.h @@ -56,5 +56,4 @@ typedef enum { CPtype = 0, UPtype } E1_t; #define GTPV1_U_PORT_NUMBER (2152) typedef enum { non_dynamic, dynamic } fiveQI_type_t; -#define maxSRBs 4 #endif diff --git a/openair2/RRC/NR/nr_rrc_common.h b/openair2/RRC/NR/nr_rrc_common.h index f821d842b6..e1ff2e703e 100644 --- a/openair2/RRC/NR/nr_rrc_common.h +++ b/openair2/RRC/NR/nr_rrc_common.h @@ -28,7 +28,7 @@ #define NR_RRC_HEADER_SIZE_MAX 64 #define NR_RRC_BUFFER_SIZE_MAX 1024 -#define NR_NUM_SRB 4 +#define NR_NUM_SRB 4 /* Number of Signalling Radio Bearers according to clause 4.2.2 of 3GPP TS 38.331 */ #define NR_K_KEY_SIZE 16 /* K keys have 128 bits length */ typedef struct { diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h index b26ff1e50c..f0d4039033 100644 --- a/openair2/RRC/NR/nr_rrc_defs.h +++ b/openair2/RRC/NR/nr_rrc_defs.h @@ -241,7 +241,7 @@ typedef struct gNB_RRC_UE_s { drb_t established_drbs[MAX_DRBS_PER_UE]; NR_DRB_ToReleaseList_t *DRB_ReleaseList; - NR_SRB_INFO_TABLE_ENTRY Srb[maxSRBs]; // 3gpp max is 3 SRBs, number 1..3, we waste the entry 0 for code simplicity + NR_SRB_INFO_TABLE_ENTRY Srb[NR_NUM_SRB]; NR_MeasConfig_t *measConfig; NR_HANDOVER_INFO *handover_info; NR_MeasResults_t *measResults; diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index e85eef0685..e2062b05ff 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -348,7 +348,7 @@ static NR_SRB_ToAddModList_t *createSRBlist(gNB_RRC_UE_t *ue, bool reestablish) return NULL; } NR_SRB_ToAddModList_t *list = CALLOC(sizeof(*list), 1); - for (int i = 0; i < maxSRBs; i++) + for (int i = 0; i < NR_NUM_SRB; i++) if (ue->Srb[i].Active) { asn1cSequenceAdd(list->list, NR_SRB_ToAddMod_t, srb); srb->srb_Identity = i; @@ -918,7 +918,8 @@ static void rrc_gNB_generate_RRCReestablishment(rrc_gNB_ue_context_t *ue_context uint8_t security_mode = enable_ciphering ? ue_p->ciphering_algorithm | (ue_p->integrity_algorithm << 4) : 0 | (ue_p->integrity_algorithm << 4); - for (int srb_id = 1; srb_id < maxSRBs; srb_id++) { + /* SRBs */ + for (int srb_id = 1; srb_id < NR_NUM_SRB; srb_id++) { if (ue_p->Srb[srb_id].Active) { nr_pdcp_config_set_security(ue_p->rrc_ue_id, srb_id, security_mode, kRRCenc, kRRCint, kUPenc); // TODO: should send E1 UE Bearer Modification with PDCP Reestablishment flag From b6087da1b26ab131d666157d11de5cfab7eaf39a Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Mon, 5 Feb 2024 15:46:41 +0100 Subject: [PATCH 03/10] Separated E1 Bearer Context Setup from Modification procedures - many structs and definitions are overlapping between the two different E1 procedures - introduced naming specific to E1 Bearer Context Modification to improve readability - grouped SDAP and PDCP configuration IEs for better reusability and readability - introduced functions to set and get default PDCP config (DRBs and Bearer Contexts) find_or_next_pdu_session: - find_or_next_pdu_session refers to the E1 Bearer Context Modification Request -- therefore it has to return pdu_session_to_mod_t* and takes in input e1ap_bearer_mod_req_t * see !MR2545 for more context --- openair2/COMMON/e1ap_messages_def.h | 2 +- openair2/COMMON/e1ap_messages_types.h | 64 +++++++++++++++----- openair2/E1AP/e1ap.c | 67 ++++++++++----------- openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c | 26 ++++---- openair2/RRC/NR/cucp_cuup_direct.c | 2 +- openair2/RRC/NR/cucp_cuup_e1ap.c | 4 +- openair2/RRC/NR/rrc_gNB.c | 41 +++++++------ openair2/RRC/NR/rrc_gNB_NGAP.c | 19 +++--- openair2/RRC/NR/rrc_gNB_radio_bearers.c | 39 +++++++----- openair2/RRC/NR/rrc_gNB_radio_bearers.h | 3 + 10 files changed, 150 insertions(+), 117 deletions(-) diff --git a/openair2/COMMON/e1ap_messages_def.h b/openair2/COMMON/e1ap_messages_def.h index df72a99f7f..5001f72885 100644 --- a/openair2/COMMON/e1ap_messages_def.h +++ b/openair2/COMMON/e1ap_messages_def.h @@ -39,7 +39,7 @@ MESSAGE_DEF(E1AP_BEARER_CONTEXT_SETUP_REQ , MESSAGE_PRIORITY_MED , e1ap_bearer_s /* E1AP Bearer Context Setup Response: gNB-CU-UP -> gNB-CU-CP */ MESSAGE_DEF(E1AP_BEARER_CONTEXT_SETUP_RESP , MESSAGE_PRIORITY_MED , e1ap_bearer_setup_resp_t , e1ap_bearer_setup_resp) /* E1AP Bearer Context Modification Request: gNB-CU-CP -> gNB-CU-UP */ -MESSAGE_DEF(E1AP_BEARER_CONTEXT_MODIFICATION_REQ , MESSAGE_PRIORITY_MED , e1ap_bearer_setup_req_t , e1ap_bearer_mod_req) +MESSAGE_DEF(E1AP_BEARER_CONTEXT_MODIFICATION_REQ , MESSAGE_PRIORITY_MED , e1ap_bearer_mod_req_t , e1ap_bearer_mod_req) /* E1AP Bearer Context Modification Response: gNB-CU-UP -> gNB-CU-CP */ MESSAGE_DEF(E1AP_BEARER_CONTEXT_MODIFICATION_RESP, MESSAGE_PRIORITY_MED, e1ap_bearer_modif_resp_t, e1ap_bearer_modif_resp) /* E1AP Bearer Context Release Request: gNB-CU-CP -> gNB-CU-UP */ diff --git a/openair2/COMMON/e1ap_messages_types.h b/openair2/COMMON/e1ap_messages_types.h index 43d63924e0..486f4d3ecd 100644 --- a/openair2/COMMON/e1ap_messages_types.h +++ b/openair2/COMMON/e1ap_messages_types.h @@ -47,7 +47,7 @@ #define E1AP_SETUP_FAIL(mSGpTR) (mSGpTR)->ittiMsg.e1ap_setup_fail #define E1AP_BEARER_CONTEXT_SETUP_REQ(mSGpTR) (mSGpTR)->ittiMsg.e1ap_bearer_setup_req #define E1AP_BEARER_CONTEXT_SETUP_RESP(mSGpTR) (mSGpTR)->ittiMsg.e1ap_bearer_setup_resp -#define E1AP_BEARER_CONTEXT_MODIFICATION_REQ(mSGpTR) (mSGpTR)->ittiMsg.e1ap_bearer_setup_req +#define E1AP_BEARER_CONTEXT_MODIFICATION_REQ(mSGpTR) (mSGpTR)->ittiMsg.e1ap_bearer_mod_req #define E1AP_BEARER_CONTEXT_MODIFICATION_RESP(mSGpTR) (mSGpTR)->ittiMsg.e1ap_bearer_modif_resp #define E1AP_BEARER_CONTEXT_RELEASE_CMD(mSGpTR) (mSGpTR)->ittiMsg.e1ap_bearer_release_cmd #define E1AP_BEARER_CONTEXT_RELEASE_CPLT(mSGpTR) (mSGpTR)->ittiMsg.e1ap_bearer_release_cplt @@ -111,11 +111,26 @@ typedef struct up_params_s { int cell_group_id; } up_params_t; -typedef struct drb_to_setup_s { - long drbId; +/* IE SDAP Configuration (clause 9.3.1.39 of 3GPP TS 38.463) */ +typedef struct bearer_context_sdap_config_s { + long defaultDRB; + long sDAP_Header_UL; + long sDAP_Header_DL; +} bearer_context_sdap_config_t; + +/* IE PDCP Configuration (clause 9.3.1.38 of 3GPP TS 38.463) */ +typedef struct bearer_context_pdcp_config_s { long pDCP_SN_Size_UL; long pDCP_SN_Size_DL; long rLC_Mode; + long reorderingTimer; + long discardTimer; + long pDCP_Reestablishment; +} bearer_context_pdcp_config_t; + +typedef struct drb_to_setup_s { + long drbId; + bearer_context_pdcp_config_t pdcp_config; long qci; long qosPriorityLevel; long pre_emptionCapability; @@ -161,26 +176,38 @@ typedef struct qos_flow_setup_e { qos_flow_level_qos_parameters_t qos_params; } qos_flow_to_setup_t; +/* DRB To Setup List according to 3GPP TS 38.463 */ typedef struct DRB_nGRAN_to_setup_s { + /* DRB ID (clause 9.3.1.16) */ long id; - long defaultDRB; - long sDAP_Header_UL; - long sDAP_Header_DL; - long pDCP_SN_Size_UL; - long pDCP_SN_Size_DL; - long discardTimer; - long reorderingTimer; - long rLC_Mode; + + /* SDAP Configuration (clause 9.3.1.39) */ + bearer_context_sdap_config_t sdap_config; + /* PDCP Configuration (clause 9.3.1.38) */ + bearer_context_pdcp_config_t pdcp_config; + + /* DRB Data Forwarding Information (clause 9.3.2.6) */ + /* Transport Layer Address (clause 9.3.2.4) */ in_addr_t tlAddress; + /* GTP-TEID (clause 9.3.2.3) */ int teId; + /* DL UP Transport Layer Information (clause 9.3.2.1) */ int numDlUpParam; up_params_t DlUpParamList[E1AP_MAX_NUM_UP_PARAM]; + + /* Cell Group Information (clause 9.3.1.11) */ int numCellGroups; cell_group_t cellGroupList[E1AP_MAX_NUM_CELL_GROUPS]; + + /* DRB QoS Flows Parameters (clause 9.3.1.26) */ int numQosFlow2Setup; qos_flow_to_setup_t qosFlows[E1AP_MAX_NUM_QOS_FLOWS]; -} DRB_nGRAN_to_setup_t; +} DRB_nGRAN_to_setup_t, DRB_nGRAN_to_mod_t; +/** + * PDU Session Resource To Setup List (clause 9.3.3.10) + * PDU Session Resource To Modify List (clause 9.3.3.11) +*/ typedef struct pdu_session_to_setup_s { long sessionId; long sessionType; @@ -196,9 +223,14 @@ typedef struct pdu_session_to_setup_s { long numDRB2Setup; DRB_nGRAN_to_setup_t DRBnGRanList[E1AP_MAX_NUM_NGRAN_DRB]; long numDRB2Modify; - DRB_nGRAN_to_setup_t DRBnGRanModList[E1AP_MAX_NUM_NGRAN_DRB]; -} pdu_session_to_setup_t; + DRB_nGRAN_to_mod_t DRBnGRanModList[E1AP_MAX_NUM_NGRAN_DRB]; +} pdu_session_to_setup_t, pdu_session_to_mod_t; +/** + * Bearer Context Setup Request message, clause 9.2.2.1 of 3GPP TS 38.463 + * out of simplicity, this same struct is used for clause 9.2.2.4 + * i.e. Bearer Context Modification Request message + */ typedef struct e1ap_bearer_setup_req_s { uint32_t gNB_cu_cp_ue_id; uint32_t gNB_cu_up_ue_id; @@ -212,8 +244,8 @@ typedef struct e1ap_bearer_setup_req_s { int numPDUSessions; pdu_session_to_setup_t pduSession[E1AP_MAX_NUM_PDU_SESSIONS]; int numPDUSessionsMod; - pdu_session_to_setup_t pduSessionMod[E1AP_MAX_NUM_PDU_SESSIONS]; -} e1ap_bearer_setup_req_t; + pdu_session_to_mod_t pduSessionMod[E1AP_MAX_NUM_PDU_SESSIONS]; +} e1ap_bearer_setup_req_t, e1ap_bearer_mod_req_t; typedef struct e1ap_bearer_release_cmd_s { uint32_t gNB_cu_cp_ue_id; diff --git a/openair2/E1AP/e1ap.c b/openair2/E1AP/e1ap.c index 64ded829ed..8acc43a689 100644 --- a/openair2/E1AP/e1ap.c +++ b/openair2/E1AP/e1ap.c @@ -664,18 +664,18 @@ static int fill_BEARER_CONTEXT_SETUP_REQUEST(e1ap_bearer_setup_req_t *const bear for (DRB_nGRAN_to_setup_t *j = i->DRBnGRanList; j < i->DRBnGRanList + i->numDRB2Setup; j++) { asn1cSequenceAdd(ieC6_1->dRB_To_Setup_List_NG_RAN.list, E1AP_DRB_To_Setup_Item_NG_RAN_t, ieC6_1_1); ieC6_1_1->dRB_ID = j->id; - - ieC6_1_1->sDAP_Configuration.defaultDRB = j->defaultDRB ? E1AP_DefaultDRB_true : E1AP_DefaultDRB_false; - ieC6_1_1->sDAP_Configuration.sDAP_Header_UL = j->sDAP_Header_UL; - ieC6_1_1->sDAP_Configuration.sDAP_Header_DL = j->sDAP_Header_DL; - - ieC6_1_1->pDCP_Configuration.pDCP_SN_Size_UL = j->pDCP_SN_Size_UL; - ieC6_1_1->pDCP_Configuration.pDCP_SN_Size_DL = j->pDCP_SN_Size_DL; - asn1cCallocOne(ieC6_1_1->pDCP_Configuration.discardTimer, j->discardTimer); + /* SDAP config */ + ieC6_1_1->sDAP_Configuration.defaultDRB = j->sdap_config.defaultDRB ? E1AP_DefaultDRB_true : E1AP_DefaultDRB_false; + ieC6_1_1->sDAP_Configuration.sDAP_Header_UL = j->sdap_config.sDAP_Header_UL; + ieC6_1_1->sDAP_Configuration.sDAP_Header_DL = j->sdap_config.sDAP_Header_DL; + /* PDCP Config */ + ieC6_1_1->pDCP_Configuration.pDCP_SN_Size_UL = j->pdcp_config.pDCP_SN_Size_UL; + ieC6_1_1->pDCP_Configuration.pDCP_SN_Size_DL = j->pdcp_config.pDCP_SN_Size_DL; + asn1cCallocOne(ieC6_1_1->pDCP_Configuration.discardTimer, j->pdcp_config.discardTimer); E1AP_T_ReorderingTimer_t *roTimer = calloc(1, sizeof(E1AP_T_ReorderingTimer_t)); ieC6_1_1->pDCP_Configuration.t_ReorderingTimer = roTimer; - roTimer->t_Reordering = j->reorderingTimer; - ieC6_1_1->pDCP_Configuration.rLC_Mode = j->rLC_Mode; + roTimer->t_Reordering = j->pdcp_config.reorderingTimer; + ieC6_1_1->pDCP_Configuration.rLC_Mode = j->pdcp_config.rLC_Mode; for (cell_group_t *k = j->cellGroupList; k < j->cellGroupList + j->numCellGroups; k++) { asn1cSequenceAdd(ieC6_1_1->cell_Group_Information.list, E1AP_Cell_Group_Information_Item_t, ieC6_1_1_1); @@ -871,7 +871,7 @@ int e1apCUUP_send_BEARER_CONTEXT_SETUP_FAILURE(instance_t instance) return -1; } -void extract_BEARER_CONTEXT_SETUP_REQUEST(const E1AP_E1AP_PDU_t *pdu, e1ap_bearer_setup_req_t *bearerCxt) +static void extract_BEARER_CONTEXT_SETUP_REQUEST(const E1AP_E1AP_PDU_t *pdu, e1ap_bearer_setup_req_t *bearerCxt) { const E1AP_BearerContextSetupRequest_t *in = &pdu->choice.initiatingMessage->value.choice.BearerContextSetupRequest; E1AP_BearerContextSetupRequestIEs_t *ie; @@ -970,23 +970,20 @@ void extract_BEARER_CONTEXT_SETUP_REQUEST(const E1AP_E1AP_PDU_t *pdu, e1ap_beare E1AP_DRB_To_Setup_Item_NG_RAN_t *drb2Setup = drb2SetupList->list.array[j]; drb->id = drb2Setup->dRB_ID; - - drb->defaultDRB = drb2Setup->sDAP_Configuration.defaultDRB == E1AP_DefaultDRB_true; - drb->sDAP_Header_UL = drb2Setup->sDAP_Configuration.sDAP_Header_UL; - drb->sDAP_Header_DL = drb2Setup->sDAP_Configuration.sDAP_Header_DL; - - drb->pDCP_SN_Size_UL = drb2Setup->pDCP_Configuration.pDCP_SN_Size_UL; - drb->pDCP_SN_Size_DL = drb2Setup->pDCP_Configuration.pDCP_SN_Size_DL; - + /* SDAP */ + drb->sdap_config.defaultDRB = drb2Setup->sDAP_Configuration.defaultDRB == E1AP_DefaultDRB_true; + drb->sdap_config.sDAP_Header_UL = drb2Setup->sDAP_Configuration.sDAP_Header_UL; + drb->sdap_config.sDAP_Header_DL = drb2Setup->sDAP_Configuration.sDAP_Header_DL; + /* PDCP */ + drb->pdcp_config.pDCP_SN_Size_UL = drb2Setup->pDCP_Configuration.pDCP_SN_Size_UL; + drb->pdcp_config.pDCP_SN_Size_DL = drb2Setup->pDCP_Configuration.pDCP_SN_Size_DL; if (drb2Setup->pDCP_Configuration.discardTimer) { - drb->discardTimer = *drb2Setup->pDCP_Configuration.discardTimer; + drb->pdcp_config.discardTimer = *drb2Setup->pDCP_Configuration.discardTimer; } - if (drb2Setup->pDCP_Configuration.t_ReorderingTimer) { - drb->reorderingTimer = drb2Setup->pDCP_Configuration.t_ReorderingTimer->t_Reordering; + drb->pdcp_config.reorderingTimer = drb2Setup->pDCP_Configuration.t_ReorderingTimer->t_Reordering; } - - drb->rLC_Mode = drb2Setup->pDCP_Configuration.rLC_Mode; + drb->pdcp_config.rLC_Mode = drb2Setup->pDCP_Configuration.rLC_Mode; E1AP_Cell_Group_Information_t *cellGroupList = &drb2Setup->cell_Group_Information; drb->numCellGroups = cellGroupList->list.count; @@ -1210,11 +1207,10 @@ static int fill_BEARER_CONTEXT_MODIFICATION_REQUEST(e1ap_bearer_setup_req_t *con 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_setup_t *i = bearerCxt->pduSessionMod; i < bearerCxt->pduSessionMod + bearerCxt->numPDUSessionsMod; i++) { + 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_setup_t *j = i->DRBnGRanModList; j < i->DRBnGRanModList + i->numDRB2Modify; j++) { + 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; @@ -1236,7 +1232,7 @@ static int fill_BEARER_CONTEXT_MODIFICATION_REQUEST(e1ap_bearer_setup_req_t *con return 0; } -static void e1apCUCP_send_BEARER_CONTEXT_MODIFICATION_REQUEST(sctp_assoc_t assoc_id, e1ap_bearer_setup_req_t *const bearerCxt) +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); @@ -1314,7 +1310,7 @@ int e1apCUUP_send_BEARER_CONTEXT_MODIFICATION_FAILURE(instance_t instance) return -1; } -void extract_BEARER_CONTEXT_MODIFICATION_REQUEST(const E1AP_E1AP_PDU_t *pdu, e1ap_bearer_setup_req_t *bearerCxt) +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; @@ -1350,20 +1346,19 @@ void extract_BEARER_CONTEXT_MODIFICATION_REQUEST(const E1AP_E1AP_PDU_t *pdu, e1a DevAssert(msgNGRAN->value.present = E1AP_NG_RAN_BearerContextModificationRequest__value_PR_PDU_Session_Resource_To_Modify_List); + /* PDU Sessions to modify */ 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_setup_t *pdu_session = bearerCxt->pduSessionMod + 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_setup_t *drb = pdu_session->DRBnGRanModList + 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; E1AP_UP_Parameters_t *dl_up_paramList = drb2Mod->dL_UP_Parameters; @@ -1402,7 +1397,7 @@ int e1apCUUP_handle_BEARER_CONTEXT_MODIFICATION_REQUEST(sctp_assoc_t assoc_id, DevAssert(pdu->choice.initiatingMessage->criticality == E1AP_Criticality_reject); DevAssert(pdu->choice.initiatingMessage->value.present == E1AP_InitiatingMessage__value_PR_BearerContextModificationRequest); - e1ap_bearer_setup_req_t bearerCxt = {0}; + e1ap_bearer_mod_req_t bearerCxt = {0}; extract_BEARER_CONTEXT_MODIFICATION_REQUEST(pdu, &bearerCxt); e1_bearer_context_modif(&bearerCxt); @@ -1960,7 +1955,7 @@ void *E1AP_CUCP_task(void *arg) break; case E1AP_BEARER_CONTEXT_MODIFICATION_REQ: - e1apCUCP_send_BEARER_CONTEXT_MODIFICATION_REQUEST(assoc_id, &E1AP_BEARER_CONTEXT_SETUP_REQ(msg)); + e1apCUCP_send_BEARER_CONTEXT_MODIFICATION_REQUEST(assoc_id, &E1AP_BEARER_CONTEXT_MODIFICATION_REQ(msg)); break; case E1AP_BEARER_CONTEXT_RELEASE_CMD: diff --git a/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c b/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c index 0f1d130cb5..8118af7e0b 100644 --- a/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c +++ b/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c @@ -47,10 +47,10 @@ static void fill_DRB_configList_e1(NR_DRB_ToAddModList_t *DRB_configList, const // sdap_Config asn1cCalloc(ie->cnAssociation->choice.sdap_Config, sdap_config); sdap_config->pdu_Session = pdu->sessionId; - sdap_config->sdap_HeaderDL = drb->sDAP_Header_DL; - sdap_config->sdap_HeaderUL = drb->sDAP_Header_UL; - sdap_config->defaultDRB = drb->defaultDRB; - + /* SDAP */ + sdap_config->sdap_HeaderDL = drb->sdap_config.sDAP_Header_DL; + sdap_config->sdap_HeaderUL = drb->sdap_config.sDAP_Header_UL; + sdap_config->defaultDRB = drb->sdap_config.defaultDRB; asn1cCalloc(sdap_config->mappedQoS_FlowsToAdd, FlowsToAdd); for (int j=0; j < drb->numQosFlow2Setup; j++) { asn1cSequenceAdd(FlowsToAdd->list, NR_QFI_t, qfi); @@ -63,26 +63,22 @@ static void fill_DRB_configList_e1(NR_DRB_ToAddModList_t *DRB_configList, const ie->recoverPDCP = NULL; asn1cCalloc(ie->pdcp_Config, pdcp_config); asn1cCalloc(pdcp_config->drb, drbCfg); - asn1cCallocOne(drbCfg->discardTimer, drb->discardTimer); - asn1cCallocOne(drbCfg->pdcp_SN_SizeUL, drb->pDCP_SN_Size_UL); - asn1cCallocOne(drbCfg->pdcp_SN_SizeDL, drb->pDCP_SN_Size_DL); + asn1cCallocOne(drbCfg->discardTimer, drb->pdcp_config.discardTimer); + asn1cCallocOne(drbCfg->pdcp_SN_SizeUL, drb->pdcp_config.pDCP_SN_Size_UL); + asn1cCallocOne(drbCfg->pdcp_SN_SizeDL, drb->pdcp_config.pDCP_SN_Size_DL); drbCfg->headerCompression.present = NR_PDCP_Config__drb__headerCompression_PR_notUsed; drbCfg->headerCompression.choice.notUsed = 0; - drbCfg->integrityProtection = NULL; drbCfg->statusReportRequired = NULL; drbCfg->outOfOrderDelivery = NULL; pdcp_config->moreThanOneRLC = NULL; - pdcp_config->t_Reordering = calloc(1, sizeof(*pdcp_config->t_Reordering)); - *pdcp_config->t_Reordering = drb->reorderingTimer; + *pdcp_config->t_Reordering = drb->pdcp_config.reorderingTimer; pdcp_config->ext1 = NULL; - if (pdu->integrityProtectionIndication == 0 || // Required pdu->integrityProtectionIndication == 1) { // Preferred - asn1cCallocOne(drbCfg->integrityProtection, NR_PDCP_Config__drb__integrityProtection_enabled); + asn1cCallocOne(drbCfg->integrityProtection, NR_PDCP_Config__drb__integrityProtection_enabled); } - if (pdu->confidentialityProtectionIndication == 2) { // Not Needed asn1cCalloc(pdcp_config->ext1, ext1); asn1cCallocOne(ext1->cipheringDisabled, NR_PDCP_Config__ext1__cipheringDisabled_true); @@ -227,7 +223,7 @@ void e1_bearer_context_setup(const e1ap_bearer_setup_req_t *req) get_e1_if()->bearer_setup_response(&resp); } -void e1_bearer_context_modif(const e1ap_bearer_setup_req_t *req) +void e1_bearer_context_modif(const e1ap_bearer_mod_req_t *req) { AssertFatal(req->numPDUSessionsMod > 0, "need at least one PDU session to modify\n"); @@ -249,7 +245,7 @@ void e1_bearer_context_modif(const e1ap_bearer_setup_req_t *req) modif.pduSessionMod[i].id = req->pduSessionMod[i].sessionId; modif.pduSessionMod[i].numDRBModified = req->pduSessionMod[i].numDRB2Modify; for (int j=0; j < req->pduSessionMod[i].numDRB2Modify; j++) { - const DRB_nGRAN_to_setup_t *to_modif = &req->pduSessionMod[i].DRBnGRanModList[j]; + const DRB_nGRAN_to_mod_t *to_modif = &req->pduSessionMod[i].DRBnGRanModList[j]; DRB_nGRAN_modified_t *modified = &modif.pduSessionMod[i].DRBnGRanModList[j]; modified->id = to_modif->id; diff --git a/openair2/RRC/NR/cucp_cuup_direct.c b/openair2/RRC/NR/cucp_cuup_direct.c index ee3555a14b..97763d65d7 100644 --- a/openair2/RRC/NR/cucp_cuup_direct.c +++ b/openair2/RRC/NR/cucp_cuup_direct.c @@ -31,7 +31,7 @@ static void cucp_cuup_bearer_context_setup_direct(sctp_assoc_t assoc_id, const e e1_bearer_context_setup(req); } -static void cucp_cuup_bearer_context_modif_direct(sctp_assoc_t assoc_id, const e1ap_bearer_setup_req_t *req) +static void cucp_cuup_bearer_context_modif_direct(sctp_assoc_t assoc_id, const e1ap_bearer_mod_req_t *req) { AssertFatal(assoc_id == -1, "illegal assoc_id %d, impossible for integrated CU\n", assoc_id); e1_bearer_context_modif(req); diff --git a/openair2/RRC/NR/cucp_cuup_e1ap.c b/openair2/RRC/NR/cucp_cuup_e1ap.c index fb099178d4..b567fd76d4 100644 --- a/openair2/RRC/NR/cucp_cuup_e1ap.c +++ b/openair2/RRC/NR/cucp_cuup_e1ap.c @@ -37,12 +37,12 @@ static void cucp_cuup_bearer_context_setup_e1ap(sctp_assoc_t assoc_id, const e1a itti_send_msg_to_task (TASK_CUCP_E1, 0, msg_p); } -static void cucp_cuup_bearer_context_mod_e1ap(sctp_assoc_t assoc_id, const e1ap_bearer_setup_req_t *req) +static void cucp_cuup_bearer_context_mod_e1ap(sctp_assoc_t assoc_id, const e1ap_bearer_mod_req_t *req) { AssertFatal(assoc_id > 0, "illegal assoc_id %d\n", assoc_id); MessageDef *msg = itti_alloc_new_message(TASK_CUCP_E1, 0, E1AP_BEARER_CONTEXT_MODIFICATION_REQ); msg->ittiMsgHeader.originInstance = assoc_id; - e1ap_bearer_setup_req_t *req_msg = &E1AP_BEARER_CONTEXT_SETUP_REQ(msg); + e1ap_bearer_mod_req_t *req_msg = &E1AP_BEARER_CONTEXT_MODIFICATION_REQ(msg); memcpy(req_msg, req, sizeof(*req)); itti_send_msg_to_task(TASK_CUCP_E1, 0, msg); } diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index e2062b05ff..70a28b738e 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -97,6 +97,7 @@ #include "openair2/F1AP/f1ap_common.h" #include "openair2/F1AP/f1ap_ids.h" #include "openair2/SDAP/nr_sdap/nr_sdap_entity.h" +#include "openair2/E1AP/e1ap.h" #include "cucp_cuup_if.h" #include "BIT_STRING.h" @@ -883,6 +884,24 @@ rrc_gNB_generate_dedicatedRRCReconfiguration_release( nr_rrc_transfer_protected_rrc_message(rrc, ue_p, DCCH, buffer, size); } +/* \brief find existing PDU session inside E1AP Bearer Modif message, or + * point to new one. + * \param bearer_modif E1AP Bearer Modification Message + * \param pdu_id PDU session ID + * \return pointer to existing PDU session, or to new/unused one. */ +static pdu_session_to_mod_t *find_or_next_pdu_session(e1ap_bearer_mod_req_t *bearer_modif, int pdu_id) +{ + for (int i = 0; i < bearer_modif->numPDUSessionsMod; ++i) { + if (bearer_modif->pduSessionMod[i].sessionId == pdu_id) + return &bearer_modif->pduSessionMod[i]; + } + /* E1AP Bearer Modification has no PDU session to modify with that ID, create + * new entry */ + DevAssert(bearer_modif->numPDUSessionsMod < E1AP_MAX_NUM_PDU_SESSIONS - 1); + bearer_modif->numPDUSessionsMod += 1; + return &bearer_modif->pduSessionMod[bearer_modif->numPDUSessionsMod - 1]; +} + //----------------------------------------------------------------------------- static void rrc_gNB_generate_RRCReestablishment(rrc_gNB_ue_context_t *ue_context_pP, const uint8_t *masterCellGroup_from_DU, @@ -1741,30 +1760,12 @@ static void fill_e1_bearer_modif(DRB_nGRAN_to_setup_t *drb_e1, const f1ap_drb_to drb_e1->DlUpParamList[0].teId = drb_f1->up_dl_tnl[0].teid; } -/* \brief find existing PDU session inside E1AP Bearer Modif message, or - * point to new one. - * \param bearer_modif E1AP Bearer Modification Message - * \param pdu_id PDU session ID - * \return pointer to existing PDU session, or to new/unused one. */ -static pdu_session_to_setup_t *find_or_next_pdu_session(e1ap_bearer_setup_req_t *bearer_modif, int pdu_id) -{ - for (int i = 0; i < bearer_modif->numPDUSessionsMod; ++i) { - if (bearer_modif->pduSessionMod[i].sessionId == pdu_id) - return &bearer_modif->pduSessionMod[i]; - } - /* E1AP Bearer Modification has no PDU session to modify with that ID, create - * new entry */ - DevAssert(bearer_modif->numPDUSessionsMod < E1AP_MAX_NUM_PDU_SESSIONS - 1); - bearer_modif->numPDUSessionsMod += 1; - return &bearer_modif->pduSessionMod[bearer_modif->numPDUSessionsMod - 1]; -} - /* \brief use list of DRBs and send the corresponding bearer update message via * E1 to the CU of this UE */ static void e1_send_bearer_updates(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, f1ap_drb_to_be_setup_t *drbs) { // we assume the same UE ID in CU-UP and CU-CP - e1ap_bearer_setup_req_t req = { + e1ap_bearer_mod_req_t req = { .gNB_cu_cp_ue_id = UE->rrc_ue_id, .gNB_cu_up_ue_id = UE->rrc_ue_id, }; @@ -1776,7 +1777,7 @@ 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]; diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index 37cc52a007..2fafec982a 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -60,6 +60,7 @@ #include "f1ap_messages_types.h" #include "openair2/F1AP/f1ap_ids.h" #include "openair2/E1AP/e1ap_asnc.h" +#include "openair2/E1AP/e1ap.h" #include "NGAP_asn_constant.h" #include "NGAP_PDUSessionResourceSetupRequestTransfer.h" #include "NGAP_PDUSessionResourceModifyRequestTransfer.h" @@ -406,19 +407,13 @@ static void trigger_bearer_setup(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, pdu DRB_nGRAN_to_setup_t *drb = pdu->DRBnGRanList + j; drb->id = rrc_drb->drb_id; - + /* SDAP */ struct sdap_config_s *sdap_config = &rrc_drb->cnAssociation.sdap_config; - drb->defaultDRB = sdap_config->defaultDRB; - drb->sDAP_Header_UL = sdap_config->sdap_HeaderUL; - drb->sDAP_Header_DL = sdap_config->sdap_HeaderDL; - - struct pdcp_config_s *pdcp_config = &rrc_drb->pdcp_config; - drb->pDCP_SN_Size_UL = pdcp_config->pdcp_SN_SizeUL; - drb->pDCP_SN_Size_DL = pdcp_config->pdcp_SN_SizeDL; - drb->discardTimer = pdcp_config->discardTimer; - drb->reorderingTimer = pdcp_config->t_Reordering; - - drb->rLC_Mode = rrc->configuration.um_on_default_drb ? E1AP_RLC_Mode_rlc_um_bidirectional : E1AP_RLC_Mode_rlc_am; + drb->sdap_config.defaultDRB = sdap_config->defaultDRB; + drb->sdap_config.sDAP_Header_UL = sdap_config->sdap_HeaderUL; + drb->sdap_config.sDAP_Header_DL = sdap_config->sdap_HeaderDL; + /* PDCP */ + set_bearer_context_pdcp_config(&drb->pdcp_config, rrc_drb, rrc->configuration.um_on_default_drb); drb->numCellGroups = 1; // assume one cell group associated with a DRB diff --git a/openair2/RRC/NR/rrc_gNB_radio_bearers.c b/openair2/RRC/NR/rrc_gNB_radio_bearers.c index 303c5ae20d..205a58fc36 100644 --- a/openair2/RRC/NR/rrc_gNB_radio_bearers.c +++ b/openair2/RRC/NR/rrc_gNB_radio_bearers.c @@ -21,6 +21,7 @@ #include "rrc_gNB_radio_bearers.h" #include "oai_asn1.h" +#include "openair2/E1AP/e1ap.h" rrc_pdu_session_param_t *find_pduSession(gNB_RRC_UE_t *ue, int id, bool create) { @@ -56,6 +57,29 @@ drb_t *get_drb(gNB_RRC_UE_t *ue, uint8_t drb_id) return &ue->established_drbs[drb_id - 1]; } +void set_default_drb_pdcp_config(struct pdcp_config_s *pdcp_config, int do_drb_integrity, int do_drb_ciphering) +{ + AssertError(pdcp_config != NULL, return, "Failed to set default PDCP configuration for DRB!\n"); + pdcp_config->discardTimer = NR_PDCP_Config__drb__discardTimer_infinity; + pdcp_config->pdcp_SN_SizeDL = NR_PDCP_Config__drb__pdcp_SN_SizeDL_len18bits; + pdcp_config->pdcp_SN_SizeUL = NR_PDCP_Config__drb__pdcp_SN_SizeUL_len18bits; + pdcp_config->t_Reordering = NR_PDCP_Config__t_Reordering_ms100; + pdcp_config->headerCompression.present = NR_PDCP_Config__drb__headerCompression_PR_notUsed; + pdcp_config->headerCompression.NotUsed = 0; + pdcp_config->integrityProtection = do_drb_integrity ? NR_PDCP_Config__drb__integrityProtection_enabled : 1; + pdcp_config->ext1.cipheringDisabled = do_drb_ciphering ? 1 : NR_PDCP_Config__ext1__cipheringDisabled_true; +} + +void set_bearer_context_pdcp_config(bearer_context_pdcp_config_t *pdcp_config, drb_t *rrc_drb, bool um_on_default_drb) +{ + AssertError(rrc_drb != NULL && pdcp_config != NULL, return, "Failed to set default bearer context PDCP configuration!\n"); + pdcp_config->pDCP_SN_Size_UL = rrc_drb->pdcp_config.pdcp_SN_SizeUL; + pdcp_config->pDCP_SN_Size_DL = rrc_drb->pdcp_config.pdcp_SN_SizeDL; + pdcp_config->discardTimer = rrc_drb->pdcp_config.discardTimer; + pdcp_config->reorderingTimer = rrc_drb->pdcp_config.t_Reordering; + pdcp_config->rLC_Mode = um_on_default_drb ? E1AP_RLC_Mode_rlc_um_bidirectional : E1AP_RLC_Mode_rlc_am; +} + drb_t *generateDRB(gNB_RRC_UE_t *ue, uint8_t drb_id, const rrc_pdu_session_param_t *pduSession, @@ -95,20 +119,7 @@ drb_t *generateDRB(gNB_RRC_UE_t *ue, est_drb->status = DRB_ACTIVE; } /* PDCP Configuration */ - est_drb->pdcp_config.discardTimer = NR_PDCP_Config__drb__discardTimer_infinity; - est_drb->pdcp_config.pdcp_SN_SizeDL = NR_PDCP_Config__drb__pdcp_SN_SizeDL_len18bits; - est_drb->pdcp_config.pdcp_SN_SizeUL = NR_PDCP_Config__drb__pdcp_SN_SizeUL_len18bits; - est_drb->pdcp_config.t_Reordering = NR_PDCP_Config__t_Reordering_ms100; - est_drb->pdcp_config.headerCompression.present = NR_PDCP_Config__drb__headerCompression_PR_notUsed; - est_drb->pdcp_config.headerCompression.NotUsed = 0; - if (do_drb_integrity) - est_drb->pdcp_config.integrityProtection = NR_PDCP_Config__drb__integrityProtection_enabled; - else - est_drb->pdcp_config.integrityProtection = 1; - if (do_drb_ciphering) - est_drb->pdcp_config.ext1.cipheringDisabled = 1; - else - est_drb->pdcp_config.ext1.cipheringDisabled = NR_PDCP_Config__ext1__cipheringDisabled_true; + set_default_drb_pdcp_config(&est_drb->pdcp_config, do_drb_integrity, do_drb_ciphering); drb_t *rrc_drb = get_drb(ue, drb_id); DevAssert(rrc_drb == est_drb); /* to double check that we create the same which we would retrieve */ diff --git a/openair2/RRC/NR/rrc_gNB_radio_bearers.h b/openair2/RRC/NR/rrc_gNB_radio_bearers.h index d29f3635ab..82502d8669 100644 --- a/openair2/RRC/NR/rrc_gNB_radio_bearers.h +++ b/openair2/RRC/NR/rrc_gNB_radio_bearers.h @@ -71,4 +71,7 @@ rrc_pdu_session_param_t *find_pduSession(gNB_RRC_UE_t *ue, int id, bool create); /// @brief get PDU session of UE ue through the DRB drb_id rrc_pdu_session_param_t *find_pduSession_from_drbId(gNB_RRC_UE_t *ue, int drb_id); +/// @brief set PDCP configuration in a bearer context management message +void set_bearer_context_pdcp_config(bearer_context_pdcp_config_t *pdcp_config, drb_t *rrc_drb, bool um_on_default_drb); + #endif From b1f9e9d57ad062096f966ea9eb3892cb536e901b Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 13 Feb 2024 12:16:37 +0100 Subject: [PATCH 04/10] Reestablishment: preserve additional secondaryUE data The previous code removed the "secondary UE" data (about DU association, DU UE ID, associated CU UP), and only filled the F1-related data. In other words, the associated CU-UP was lost. This commit reworks this piece of code to retrieve old data, and update the relevant data without destroying other. --- openair2/RRC/NR/rrc_gNB.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 70a28b738e..acc5233151 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -1203,8 +1203,9 @@ static void rrc_handle_RRCReestablishmentRequest(gNB_RRC_INST *rrc, sctp_assoc_t // update with new RNTI, and update secondary UE association UE->rnti = msg->crnti; + f1_ue_data_t ue_data = cu_get_f1_ue_data(UE->rrc_ue_id); + ue_data.secondary_ue = msg->gNB_DU_ue_id; cu_remove_f1_ue_data(UE->rrc_ue_id); - f1_ue_data_t ue_data = {.secondary_ue = msg->gNB_DU_ue_id, .du_assoc_id = assoc_id}; cu_add_f1_ue_data(UE->rrc_ue_id, &ue_data); LOG_I(NR_RRC, "Accept Reestablishment Request UE physCellId %ld cause %s\n", physCellId, scause); From c83ff4c388c5856c442ca7c5156fc8ddb505b054 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Thu, 22 Feb 2024 12:19:30 +0100 Subject: [PATCH 05/10] Store F1-U downlink TL and TEID - info coming from UE context setup/modification response messages in RRC --- openair2/COMMON/ngap_messages_types.h | 6 ++++-- openair2/RRC/NR/nr_rrc_defs.h | 12 ++++++++++++ openair2/RRC/NR/rrc_gNB.c | 12 ++++++++++++ 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/openair2/COMMON/ngap_messages_types.h b/openair2/COMMON/ngap_messages_types.h index caf0bff683..0c9be504ca 100644 --- a/openair2/COMMON/ngap_messages_types.h +++ b/openair2/COMMON/ngap_messages_types.h @@ -276,12 +276,14 @@ typedef struct pdusession_s { /* The transport layer address for the IP packets */ pdu_session_type_t pdu_session_type; transport_layer_addr_t upf_addr; - /* S-GW Tunnel endpoint identifier */ + /* Outgoing (UL) NG-U Tunnel Endpoint Identifier (S-GW/UPF) */ uint32_t gtp_teid; /* Stores the DRB ID of the DRBs used by this PDU Session */ uint8_t used_drbs[MAX_DRBS_PER_UE]; + /* Incoming (DL) NG-U Tunnel Endpoint Identifier (S-GW/UPF) */ uint32_t gNB_teid_N3; transport_layer_addr_t gNB_addr_N3; + /* Incoming (DL) NG-U Tunnel Endpoint Identifier (S-GW/UPF) */ uint32_t UPF_teid_N3; transport_layer_addr_t UPF_addr_N3; nssai_t nssai; @@ -306,7 +308,7 @@ typedef struct pdusession_setup_s { uint8_t pdu_session_type; transport_layer_addr_t gNB_addr; - /* UPF Tunnel endpoint identifier */ + /* Incoming NG-U Tunnel Endpoint Identifier (S-GW/UPF) */ uint32_t gtp_teid; /* qos flow list number */ diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h index f0d4039033..4dc17fd493 100644 --- a/openair2/RRC/NR/nr_rrc_defs.h +++ b/openair2/RRC/NR/nr_rrc_defs.h @@ -189,6 +189,16 @@ typedef struct pdu_session_param_s { uint8_t cause_value; } rrc_pdu_session_param_t; +/** + * @brief F1-U tunnel configuration +*/ +typedef struct f1u_tunnel_s { + /* Downlink F1-U Tunnel Endpoint Identifier (CU-UP/DU) */ + uint32_t cuup_teid_f1u; + /* DL F1-U Transport Layer */ + transport_layer_addr_t cuup_addr_f1u; +} f1u_tunnel_t; + typedef struct drb_s { int status; int defaultDRBid; @@ -221,6 +231,8 @@ typedef struct drb_s { int cipheringDisabled; } ext1; } pdcp_config; + // F1-U + f1u_tunnel_t f1u_tunnel_config; } drb_t; typedef enum { diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index acc5233151..4e7505bcd0 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -1761,6 +1761,16 @@ static void fill_e1_bearer_modif(DRB_nGRAN_to_setup_t *drb_e1, const f1ap_drb_to drb_e1->DlUpParamList[0].teId = drb_f1->up_dl_tnl[0].teid; } +/** + * @brief Store F1-U DL TL and TEID in RRC +*/ +static void f1u_gtp_update(f1u_tunnel_t *f1u, const f1ap_drb_to_be_setup_t *drb_f1) +{ + f1u->cuup_teid_f1u = drb_f1->up_dl_tnl[0].teid; + memcpy(&f1u->cuup_addr_f1u.buffer, &drb_f1->up_dl_tnl[0].tl_address, sizeof(uint8_t) * 4); + f1u->cuup_addr_f1u.length = sizeof(in_addr_t); +} + /* \brief use list of DRBs and send the corresponding bearer update message via * E1 to the CU of this UE */ static void e1_send_bearer_updates(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, f1ap_drb_to_be_setup_t *drbs) @@ -1782,6 +1792,8 @@ static void e1_send_bearer_updates(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, f 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]; + f1u_gtp_update(&UE->established_drbs[drb_f1->drb_id].f1u_tunnel_config, drb_f1); + /* Fill E1 bearer context modification */ fill_e1_bearer_modif(drb_e1, drb_f1); pdu_e1->numDRB2Modify += 1; } From 2a078c757b2cfee76023b9479a0afa63c41997bd Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Wed, 31 Jan 2024 10:13:27 +0100 Subject: [PATCH 06/10] E1 Reestablishment - PDCP reestablishment on CUCP (DRBs) triggering Bearer Context Modification procedures over E1 - Performing PDCP reestablishment for requested DRBs on CUUP - Introduced function to notify re-establishment to CU-UP - removed call to PDCP reestablishment for the DRBs on CUCP (it's done on CUUP) cuup_notify_reestablishment: - to fetch PDU session to setup in E1 following logic as in e1_send_bearer_updates - fill bearer context modification request with stored F1-U tunnel information during E1 reestablishment, otherwise it would initialized to 0 by default - update GTP tunnel with the stored configuration after E1 reestablishment --- openair2/COMMON/e1ap_messages_types.h | 2 +- openair2/E1AP/e1ap.c | 40 +++++++----- openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c | 4 ++ openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c | 4 ++ openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c | 3 +- openair2/RRC/NR/rrc_gNB.c | 68 ++++++++++++++++++--- 6 files changed, 94 insertions(+), 27 deletions(-) diff --git a/openair2/COMMON/e1ap_messages_types.h b/openair2/COMMON/e1ap_messages_types.h index 486f4d3ecd..5b727a3818 100644 --- a/openair2/COMMON/e1ap_messages_types.h +++ b/openair2/COMMON/e1ap_messages_types.h @@ -125,7 +125,7 @@ typedef struct bearer_context_pdcp_config_s { long rLC_Mode; long reorderingTimer; long discardTimer; - long pDCP_Reestablishment; + bool pDCP_Reestablishment; } bearer_context_pdcp_config_t; typedef struct drb_to_setup_s { diff --git a/openair2/E1AP/e1ap.c b/openair2/E1AP/e1ap.c index 8acc43a689..ca1a7e179e 100644 --- a/openair2/E1AP/e1ap.c +++ b/openair2/E1AP/e1ap.c @@ -1214,7 +1214,10 @@ static int fill_BEARER_CONTEXT_MODIFICATION_REQUEST(e1ap_bearer_setup_req_t *con 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.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++) { @@ -1360,21 +1363,28 @@ static void extract_BEARER_CONTEXT_MODIFICATION_REQUEST(const E1AP_E1AP_PDU_t *p 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; - - 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->tlAddress); - OCTET_STRING_TO_INT32(&dl_up_param_in->uP_TNL_Information.choice.gTPTunnel->gTP_TEID, dl_up_param->teId); - } else { - AssertFatal(false, "gTPTunnel IE is missing. It is mandatory at this point\n"); + 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; + } + 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->tlAddress); + OCTET_STRING_TO_INT32(&dl_up_param_in->uP_TNL_Information.choice.gTPTunnel->gTP_TEID, dl_up_param->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; } - dl_up_param->cell_group_id = dl_up_param_in->cell_Group_ID; } } } diff --git a/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c b/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c index 8118af7e0b..7faf9a5b5e 100644 --- a/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c +++ b/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c @@ -249,6 +249,10 @@ 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) { + nr_pdcp_reestablishment(req->gNB_cu_up_ue_id, to_modif->id, false); + } + if (f1inst < 0) // no F1-U? continue; // nothing to do diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c index 0bbd294c53..381152b5c5 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c @@ -409,6 +409,10 @@ static void free_rx_list(nr_pdcp_entity_t *entity) entity->rx_size = 0; } +/** + * @brief PDCP entity re-establishment according to 5.1.2 of 3GPP TS 38.323 + * @todo deal with ciphering/integrity algos and keys for transmitting/receiving entity procedures +*/ static void nr_pdcp_entity_reestablish_drb_am(nr_pdcp_entity_t *entity) { /* transmitting entity procedures */ diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c index 73e015976d..db78c4108b 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c @@ -1210,9 +1210,10 @@ void nr_pdcp_reestablishment(ue_id_t ue_id, int rb_id, bool srb_flag) rb = nr_pdcp_get_rb(ue, rb_id, srb_flag); if (rb != NULL) { + LOG_D(PDCP, "UE %4.4lx re-establishment of %sRB %d\n", ue_id, srb_flag ? "S" : "D", rb_id); rb->reestablish_entity(rb); } else { - LOG_W(PDCP, "UE %4.4lx cannot re-establish RB %d (is_srb %d), RB not found\n", ue_id, rb_id, srb_flag); + LOG_W(PDCP, "UE %4.4lx cannot re-establish %sRB %d, RB not found\n", ue_id, srb_flag ? "S" : "D", rb_id); } nr_pdcp_manager_unlock(nr_pdcp_ue_manager); diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 4e7505bcd0..6f91b98bb2 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -902,7 +902,60 @@ static pdu_session_to_mod_t *find_or_next_pdu_session(e1ap_bearer_mod_req_t *bea return &bearer_modif->pduSessionMod[bearer_modif->numPDUSessionsMod - 1]; } -//----------------------------------------------------------------------------- +/** + * @brief Notify E1 re-establishment to CU-UP + */ +static void cuup_notify_reestablishment(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue_p) +{ + e1ap_bearer_mod_req_t req = { + .gNB_cu_cp_ue_id = ue_p->rrc_ue_id, + .gNB_cu_up_ue_id = ue_p->rrc_ue_id, + }; + if (!ue_associated_to_cuup(rrc, ue_p)) + return; + /* loop through active DRBs */ + for (int drb_id = 1; drb_id <= MAX_DRBS_PER_UE; drb_id++) { + if (ue_p->established_drbs[drb_id - 1].status == DRB_INACTIVE) + continue; + /* fetch an existing PDU session for this DRB */ + rrc_pdu_session_param_t *pdu = find_pduSession_from_drbId(ue_p, drb_id); + if (pdu == NULL) { + LOG_E(RRC, "UE %d: E1 Bearer Context Modification: no PDU session for DRB ID %d\n", ue_p->rrc_ue_id, drb_id); + continue; + } + /* Get pointer to existing (or new one) PDU session to modify in E1 */ + pdu_session_to_mod_t *pdu_e1 = find_or_next_pdu_session(&req, pdu->param.pdusession_id); + AssertError(pdu != NULL, + continue, + "UE %d: E1 Bearer Context Modification: PDU session %d to setup is null\n", + ue_p->rrc_ue_id, + pdu->param.pdusession_id); + /* Prepare PDU for E1 Bearear Context Modification Request */ + pdu_e1->sessionId = pdu->param.pdusession_id; + /* Fill DRB to setup with ID, DL TL and DL TEID */ + DRB_nGRAN_to_mod_t *drb_e1 = &pdu_e1->DRBnGRanModList[pdu_e1->numDRB2Modify]; + drb_e1->id = drb_id; + drb_e1->numDlUpParam = 1; + drb_t *drbs = &ue_p->established_drbs[drb_id]; + memcpy(&drb_e1->DlUpParamList[0].tlAddress, &drbs->f1u_tunnel_config.cuup_addr_f1u.buffer, sizeof(uint8_t) * 4); + drb_e1->DlUpParamList[0].teId = drbs->f1u_tunnel_config.cuup_teid_f1u; + /* PDCP configuration */ + bearer_context_pdcp_config_t *pdcp_config = &drb_e1->pdcp_config; + drb_t *rrc_drb = get_drb(ue_p, drb_id); + set_bearer_context_pdcp_config(pdcp_config, rrc_drb, rrc->configuration.um_on_default_drb); + pdcp_config->pDCP_Reestablishment = true; + /* increase DRB to modify counter */ + pdu_e1->numDRB2Modify += 1; + } + /* Send E1 Bearer Context Modification Request (3GPP TS 38.463) */ + sctp_assoc_t assoc_id = get_existing_cuup_for_ue(rrc, ue_p); + rrc->cucp_cuup.bearer_context_mod(assoc_id, &req); +} + +/** + * @brief RRCReestablishment message + * Direction: Network to UE + */ static void rrc_gNB_generate_RRCReestablishment(rrc_gNB_ue_context_t *ue_context_pP, const uint8_t *masterCellGroup_from_DU, const rnti_t old_rnti, @@ -941,17 +994,12 @@ static void rrc_gNB_generate_RRCReestablishment(rrc_gNB_ue_context_t *ue_context for (int srb_id = 1; srb_id < NR_NUM_SRB; srb_id++) { if (ue_p->Srb[srb_id].Active) { nr_pdcp_config_set_security(ue_p->rrc_ue_id, srb_id, security_mode, kRRCenc, kRRCint, kUPenc); - // TODO: should send E1 UE Bearer Modification with PDCP Reestablishment flag nr_pdcp_reestablishment(ue_p->rrc_ue_id, srb_id, true); } } - - // TODO: should send E1 UE Bearer Modification with PDCP Reestablishment flag - for (int drb_id = 1; drb_id <= MAX_DRBS_PER_UE; drb_id++) { - if (ue_p->established_drbs[drb_id - 1].status != DRB_INACTIVE) - nr_pdcp_reestablishment(ue_p->rrc_ue_id, drb_id, false); - } - + /* PDCP Reestablishment over E1 */ + cuup_notify_reestablishment(rrc, ue_p); + /* F1AP DL RRC Message Transfer */ f1_ue_data_t ue_data = cu_get_f1_ue_data(ue_p->rrc_ue_id); RETURN_IF_INVALID_ASSOC_ID(ue_data); uint32_t old_gNB_DU_ue_id = old_rnti; @@ -1788,7 +1836,7 @@ 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_mod_t *pdu_e1 = find_or_next_pdu_session(&req, pdu_ue->param.pdusession_id); + pdu_session_to_setup_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]; From 72166d7ae943ca4566b3eca0944df98169cdc129 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Wed, 31 Jan 2024 12:20:54 +0100 Subject: [PATCH 07/10] E1AP procedures documentation - new folder dedicated to E1AP docs - new file to document E1AP procedures --- doc/{ => E1AP}/E1-design.md | 4 +- doc/E1AP/e1ap_procedures.md | 74 +++++++++++++++++++++++++++++++++++++ doc/README.md | 2 +- 3 files changed, 77 insertions(+), 3 deletions(-) rename doc/{ => E1AP}/E1-design.md (97%) create mode 100644 doc/E1AP/e1ap_procedures.md diff --git a/doc/E1-design.md b/doc/E1AP/E1-design.md similarity index 97% rename from doc/E1-design.md rename to doc/E1AP/E1-design.md index 6939e3867e..eb7e373e7b 100644 --- a/doc/E1-design.md +++ b/doc/E1AP/E1-design.md @@ -75,11 +75,11 @@ sequenceDiagram Note over u: E1AP_CUUP_task (SCTP Handler) Note over u: ASN1 decoder ``` - +More details about the E1AP procedures in OAI are available in this document: [E1 Procedures](./e1ap_procedures.md). # 2. Running the E1 Split -The setup is assuming that all modules are running on the same machine. The user can refer to the [F1 design document](./F1-design.md) for local deployment of the DU. +The setup is assuming that all modules are running on the same machine. The user can refer to the [F1 design document](./../F1-design.md) for local deployment of the DU. ## 2.1 Configuration File diff --git a/doc/E1AP/e1ap_procedures.md b/doc/E1AP/e1ap_procedures.md new file mode 100644 index 0000000000..c46c710333 --- /dev/null +++ b/doc/E1AP/e1ap_procedures.md @@ -0,0 +1,74 @@ + + + + + +
+ + + + + + E1AP Procedures +
+ +[[_TOC_]] + +# Introduction +The E1 interface is between the gNB-CU-CP (Central Unit - Control Plane) and gNB-CU-UP (Central Unit - User Plane) nodes. This interface is governed by the E1 Application Protocol (E1AP) outlined in the 3GPP release 16 specifications, specifically in the documents: +* 3GPP TS 38.463 - E1 Application Protocol (E1AP) +* 3GPP TS 38.460 - E1 general aspects and principles +* 3GPP TS 38.461 - E1 interface: layer 1 +* 3GPP TS 38.462 - E1 interface: signaling transport + +The E1AP protocol consists of the following sets of functions: +* E1 Interface Management functions +* E1 Bearer Context Management functions +* TEID allocation function + +## E1 Bearer Context Management function +This function handles the establishment, modification, and release of E1 bearer contexts. +* E1 Bearer Context Establishment: initiation of E1 bearer context is by gNB-CU-CP and acceptance or rejection is determined by gNB-CU-UP based on admission control criteria (e.g., resource availability). +* E1 Bearer Context Modification: can be initiated by either gNB-CU-CP or gNB-CU-UP, with the receiving node having the authority to accept or reject the modification. +* Release of Bearer Context: can be triggered either directly by gNB-CU-CP or following a request from gNB-CU-UP. +* QoS-Flow to DRB Mapping Configuration: responsible for setting up and modifying the QoS-flow to DRB mapping configuration. gNB-CU-CP decides the flow-to-DRB mapping, generates SDAP and PDCP configurations, and provides them to gNB-CU-UP. + +# OAI implementation + +For the E1AP design in OAI, please refer to the [E1 Design](./E1-design.md) document. + +## E1 re-establishment + +The purpose of this procedure is to follow-up the re-establishment of RRC connection over the E1 interface. For all activated DRBs a Bearer Context Modification from CU-CP to CU-UP is necessary, according to clause 9.2.2.4 of 3GPP TS 38.463. If any modification to the bearer context is required, the CU-CP informs the CU-UP with the relevant IEs (e.g. in case of PDCP re-establishment, PDCP Configuration IE clause 9.3.1.38), Current implementation in OAI: + +```mermaid +sequenceDiagram + participant e as UE + participant d as DU + participant c as CUCP + participant u as CUUP + + Note over e,c: RRCReestablishment Procedure + e->>d: RRCReestablishmentRequest + Note over d: initial_ul_rrc_message_transfer_f1ap + d->>+c: Initial UL RRC Message Transfer (CCCH, new C-RNTI) + Note over c: rrc_gNB_process_initial_ul_rrc_message + Note over c: rrc_handle_RRCReestablishmentRequests + c-->>+d: DL RRC Message Transfer + note right of d: fallback to RRC establishment + d-->>-e: RRCSetup + e-->>d: RRCSetupComplete + Note over c: rrc_gNB_generate_RRCReestablishment + Note over c: cuup_notify_reestablishment + Note over c: e1apCUCP_send_BEARER_CONTEXT_MODIFICATION_REQUEST + c->>u: BEARER CONTEXT MODIFICATION REQUEST + Note over u: e1apCUUP_handle_BEARER_CONTEXT_MODIFICATION_REQUEST + Note over u: e1_bearer_context_modif + Note over u: nr_pdcp_reestablishment + c->>-d: DL RRC Message Transfer (old gNB DU F1AP UE ID) + d->>e: RRCReestablishment + Note over d: Fetch UE Context with old gNB DU F1AP UE ID and update C-RNTI + e->>d: RRCReestablishmentComplete + u->>c: BEARER CONTEXT MODIFICATION RESPONSE + Note over c: e1apCUCP_handle_BEARER_CONTEXT_MODIFICATION_RESPONSE +``` diff --git a/doc/README.md b/doc/README.md index 9ff7079f8b..1ceba8f494 100644 --- a/doc/README.md +++ b/doc/README.md @@ -57,7 +57,7 @@ Legacy unmaintained files: # Designs - General software architecture notes: [SW_archi.md](./SW_archi.md) -- [Information on E1](./E1-design.md) +- [Information on E1](./E1AP/E1-design.md) - [Information on F1](./F1-design.md) - [Information on how NR nFAPI works](./NR_NFAPI_archi.md) - [Flow graph of the L1 in gNB](SW-archi-graph.md) From ffd176e9d5164c02cbdbdae9718ef9ab430419dc Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Wed, 31 Jan 2024 10:33:17 +0100 Subject: [PATCH 08/10] Minor fixes, comments, Clang formatting - comments to improve readability of the code - Clang formatting of E1 / RRC (partial) --- openair2/E1AP/e1ap.c | 58 +++++++------ openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c | 13 ++- openair2/RRC/NR/rrc_gNB.c | 93 ++++++++++++++------- 3 files changed, 102 insertions(+), 62 deletions(-) diff --git a/openair2/E1AP/e1ap.c b/openair2/E1AP/e1ap.c index ca1a7e179e..1c9ff19bff 100644 --- a/openair2/E1AP/e1ap.c +++ b/openair2/E1AP/e1ap.c @@ -163,7 +163,6 @@ int e1ap_send_ERROR_INDICATION(instance_t instance, E1AP_ErrorIndication_t *Erro /* E1 Setup: can be sent on both ways, to be refined */ - static void fill_SETUP_REQUEST(e1ap_setup_req_t *setup, E1AP_E1AP_PDU_t *pdu) { /* Create */ @@ -676,16 +675,16 @@ static int fill_BEARER_CONTEXT_SETUP_REQUEST(e1ap_bearer_setup_req_t *const bear ieC6_1_1->pDCP_Configuration.t_ReorderingTimer = roTimer; roTimer->t_Reordering = j->pdcp_config.reorderingTimer; ieC6_1_1->pDCP_Configuration.rLC_Mode = j->pdcp_config.rLC_Mode; - + /* Cell Group config */ for (cell_group_t *k = j->cellGroupList; k < j->cellGroupList + j->numCellGroups; k++) { asn1cSequenceAdd(ieC6_1_1->cell_Group_Information.list, E1AP_Cell_Group_Information_Item_t, ieC6_1_1_1); ieC6_1_1_1->cell_Group_ID = k->id; } - + /* QoS Flows */ for (qos_flow_to_setup_t *k = j->qosFlows; k < j->qosFlows + j->numQosFlow2Setup; k++) { asn1cSequenceAdd(ieC6_1_1->qos_flow_Information_To_Be_Setup, E1AP_QoS_Flow_QoS_Parameter_Item_t, ieC6_1_1_1); ieC6_1_1_1->qoS_Flow_Identifier = k->qfi; - + /* QoS Characteristics */ qos_characteristics_t *qos_char_in = &k->qos_params.qos_characteristics; if (qos_char_in->qos_type == non_dynamic) { // non Dynamic 5QI ieC6_1_1_1->qoSFlowLevelQoSParameters.qoS_Characteristics.present = E1AP_QoS_Characteristics_PR_non_Dynamic_5QI; @@ -699,7 +698,7 @@ static int fill_BEARER_CONTEXT_SETUP_REQUEST(e1ap_bearer_setup_req_t *const bear dynamic_5QI->packetErrorRate.pER_Scalar = qos_char_in->dynamic.packet_error_rate.per_scalar; dynamic_5QI->packetErrorRate.pER_Exponent = qos_char_in->dynamic.packet_error_rate.per_exponent; } - + /* QoS Retention Priority */ ngran_allocation_retention_priority_t *rent_priority_in = &k->qos_params.alloc_reten_priority; ieC6_1_1_1->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.priorityLevel = rent_priority_in->priority_level; ieC6_1_1_1->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.pre_emptionCapability = @@ -1002,8 +1001,7 @@ static void extract_BEARER_CONTEXT_SETUP_REQUEST(const E1AP_E1AP_PDU_t *pdu, e1a qos_flow->qfi = qos2Setup->qoS_Flow_Identifier; qos_characteristics_t *qos_char = &qos_flow->qos_params.qos_characteristics; - if (qos2Setup->qoSFlowLevelQoSParameters.qoS_Characteristics.present == - E1AP_QoS_Characteristics_PR_non_Dynamic_5QI) { + if (qos2Setup->qoSFlowLevelQoSParameters.qoS_Characteristics.present == E1AP_QoS_Characteristics_PR_non_Dynamic_5QI) { qos_char->qos_type = non_dynamic; qos_char->non_dynamic.fiveqi = qos2Setup->qoSFlowLevelQoSParameters.qoS_Characteristics.choice.non_Dynamic_5QI->fiveQI; @@ -1075,9 +1073,11 @@ void extract_BEARER_CONTEXT_SETUP_RESPONSE(const E1AP_E1AP_PDU_t *pdu, e1ap_bear case E1AP_ProtocolIE_ID_id_System_BearerContextSetupResponse: DevAssert(ie->criticality == E1AP_Criticality_reject); DevAssert(ie->value.present == E1AP_BearerContextSetupResponseIEs__value_PR_System_BearerContextSetupResponse); - DevAssert(ie->value.choice.System_BearerContextSetupResponse.present == - E1AP_System_BearerContextSetupResponse_PR_nG_RAN_BearerContextSetupResponse); - E1AP_ProtocolIE_Container_4932P22_t *msgNGRAN_list = (E1AP_ProtocolIE_Container_4932P22_t *) ie->value.choice.System_BearerContextSetupResponse.choice.nG_RAN_BearerContextSetupResponse; + DevAssert(ie->value.choice.System_BearerContextSetupResponse.present + == E1AP_System_BearerContextSetupResponse_PR_nG_RAN_BearerContextSetupResponse); + E1AP_ProtocolIE_Container_4932P22_t *msgNGRAN_list = + (E1AP_ProtocolIE_Container_4932P22_t *) + ie->value.choice.System_BearerContextSetupResponse.choice.nG_RAN_BearerContextSetupResponse; DevAssert(msgNGRAN_list->list.count == 1); E1AP_NG_RAN_BearerContextSetupResponse_t *msgNGRAN = msgNGRAN_list->list.array[0]; DevAssert(msgNGRAN->id == E1AP_ProtocolIE_ID_id_PDU_Session_Resource_Setup_List); @@ -1093,10 +1093,10 @@ void extract_BEARER_CONTEXT_SETUP_RESPONSE(const E1AP_E1AP_PDU_t *pdu, e1ap_bear if (pdu_session->nG_DL_UP_TNL_Information.choice.gTPTunnel) { DevAssert(pdu_session->nG_DL_UP_TNL_Information.present == E1AP_UP_TNL_Information_PR_gTPTunnel); - BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&pdu_session->nG_DL_UP_TNL_Information.choice.gTPTunnel->transportLayerAddress, - pduSetup->tlAddress); - OCTET_STRING_TO_INT32(&pdu_session->nG_DL_UP_TNL_Information.choice.gTPTunnel->gTP_TEID, - pduSetup->teId); + BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4( + &pdu_session->nG_DL_UP_TNL_Information.choice.gTPTunnel->transportLayerAddress, + pduSetup->tlAddress); + OCTET_STRING_TO_INT32(&pdu_session->nG_DL_UP_TNL_Information.choice.gTPTunnel->gTP_TEID, pduSetup->teId); } pduSetup->numDRBSetup = pdu_session->dRB_Setup_List_NG_RAN.list.count; @@ -1114,10 +1114,8 @@ void extract_BEARER_CONTEXT_SETUP_RESPONSE(const E1AP_E1AP_PDU_t *pdu, e1ap_bear DevAssert(in_UL_UP_param->uP_TNL_Information.present == E1AP_UP_TNL_Information_PR_gTPTunnel); E1AP_GTPTunnel_t *gTPTunnel = in_UL_UP_param->uP_TNL_Information.choice.gTPTunnel; if (gTPTunnel) { - BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&gTPTunnel->transportLayerAddress, - UL_UP_param->tlAddress); - OCTET_STRING_TO_INT32(&gTPTunnel->gTP_TEID, - UL_UP_param->teId); + BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&gTPTunnel->transportLayerAddress, UL_UP_param->tlAddress); + OCTET_STRING_TO_INT32(&gTPTunnel->gTP_TEID, UL_UP_param->teId); } else { AssertFatal(false, "gTPTunnel information in required\n"); } @@ -1313,6 +1311,9 @@ 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; @@ -1347,9 +1348,8 @@ static void extract_BEARER_CONTEXT_MODIFICATION_REQUEST(const E1AP_E1AP_PDU_t *p 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 Sessions to modify */ + 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++) { @@ -1397,6 +1397,10 @@ static void extract_BEARER_CONTEXT_MODIFICATION_REQUEST(const E1AP_E1AP_PDU_t *p } } +/** + * @brief Extract Bearer Context Modification Request from E1AP PDU + * and prepare Bearer Context Modification Response + */ int e1apCUUP_handle_BEARER_CONTEXT_MODIFICATION_REQUEST(sctp_assoc_t assoc_id, e1ap_upcp_inst_t *e1_inst, const E1AP_E1AP_PDU_t *pdu) @@ -1406,10 +1410,8 @@ int e1apCUUP_handle_BEARER_CONTEXT_MODIFICATION_REQUEST(sctp_assoc_t assoc_id, 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; } @@ -1417,7 +1419,8 @@ int e1apCUUP_handle_BEARER_CONTEXT_MODIFICATION_REQUEST(sctp_assoc_t assoc_id, 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; + 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]; @@ -1437,7 +1440,8 @@ static void extract_BEARER_CONTEXT_MODIFICATION_RESPONSE(const E1AP_E1AP_PDU_t * 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.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 = @@ -1447,7 +1451,8 @@ static void extract_BEARER_CONTEXT_MODIFICATION_RESPONSE(const E1AP_E1AP_PDU_t * 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); + 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; @@ -1490,7 +1495,6 @@ int e1apCUCP_handle_BEARER_CONTEXT_MODIFICATION_RESPONSE(sctp_assoc_t assoc_id, 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); diff --git a/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c b/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c index 7faf9a5b5e..2b65cf87f9 100644 --- a/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c +++ b/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c @@ -37,7 +37,7 @@ static void fill_DRB_configList_e1(NR_DRB_ToAddModList_t *DRB_configList, const pdu_session_to_setup_t *pdu) { - for (int i=0; i < pdu->numDRB2Setup; i++) { + for (int i = 0; i < pdu->numDRB2Setup; i++) { const DRB_nGRAN_to_setup_t *drb = pdu->DRBnGRanList + i; asn1cSequenceAdd(DRB_configList->list, struct NR_DRB_ToAddMod, ie); ie->drb_Identity = drb->id; @@ -52,7 +52,7 @@ static void fill_DRB_configList_e1(NR_DRB_ToAddModList_t *DRB_configList, const sdap_config->sdap_HeaderUL = drb->sdap_config.sDAP_Header_UL; sdap_config->defaultDRB = drb->sdap_config.defaultDRB; asn1cCalloc(sdap_config->mappedQoS_FlowsToAdd, FlowsToAdd); - for (int j=0; j < drb->numQosFlow2Setup; j++) { + for (int j = 0; j < drb->numQosFlow2Setup; j++) { asn1cSequenceAdd(FlowsToAdd->list, NR_QFI_t, qfi); *qfi = drb->qosFlows[j].qfi; } @@ -223,6 +223,9 @@ void e1_bearer_context_setup(const e1ap_bearer_setup_req_t *req) get_e1_if()->bearer_setup_response(&resp); } +/** + * @brief Fill Bearer Context Modification Response and send to callback + */ void e1_bearer_context_modif(const e1ap_bearer_mod_req_t *req) { AssertFatal(req->numPDUSessionsMod > 0, "need at least one PDU session to modify\n"); @@ -235,7 +238,8 @@ void e1_bearer_context_modif(const e1ap_bearer_mod_req_t *req) instance_t f1inst = get_f1_gtp_instance(); - for (int i=0; i < req->numPDUSessionsMod; i++) { + /* PDU Session Resource To Modify List (see 9.3.3.11 of TS 38.463) */ + for (int i = 0; i < req->numPDUSessionsMod; i++) { DevAssert(req->pduSessionMod[i].sessionId > 0); LOG_I(E1AP, "UE %d: updating PDU session ID %ld (%ld bearers)\n", @@ -244,7 +248,8 @@ void e1_bearer_context_modif(const e1ap_bearer_mod_req_t *req) req->pduSessionMod[i].numDRB2Modify); modif.pduSessionMod[i].id = req->pduSessionMod[i].sessionId; modif.pduSessionMod[i].numDRBModified = req->pduSessionMod[i].numDRB2Modify; - for (int j=0; j < req->pduSessionMod[i].numDRB2Modify; j++) { + /* DRBs to modify */ + for (int j = 0; j < req->pduSessionMod[i].numDRB2Modify; j++) { const DRB_nGRAN_to_mod_t *to_modif = &req->pduSessionMod[i].DRBnGRanModList[j]; DRB_nGRAN_modified_t *modified = &modif.pduSessionMod[i].DRBnGRanModList[j]; modified->id = to_modif->id; diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 6f91b98bb2..c9ff93065a 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -155,15 +155,24 @@ static void rrc_deliver_dl_rrc_message(void *deliver_pdu_data, ue_id_t ue_id, in data->rrc->mac_rrc.dl_rrc_message_transfer(data->assoc_id, data->dl_rrc); } - -void nr_rrc_transfer_protected_rrc_message(const gNB_RRC_INST *rrc, const gNB_RRC_UE_t *ue_p, uint8_t srb_id, const uint8_t* buffer, int size) +void nr_rrc_transfer_protected_rrc_message(const gNB_RRC_INST *rrc, + const gNB_RRC_UE_t *ue_p, + uint8_t srb_id, + const uint8_t *buffer, + int size) { DevAssert(size > 0); f1_ue_data_t ue_data = cu_get_f1_ue_data(ue_p->rrc_ue_id); RETURN_IF_INVALID_ASSOC_ID(ue_data); f1ap_dl_rrc_message_t dl_rrc = {.gNB_CU_ue_id = ue_p->rrc_ue_id, .gNB_DU_ue_id = ue_data.secondary_ue, .srb_id = srb_id}; - deliver_dl_rrc_message_data_t data = {.rrc = rrc, .dl_rrc = &dl_rrc, .assoc_id = ue_data.du_assoc_id }; - nr_pdcp_data_req_srb(ue_p->rrc_ue_id, srb_id, rrc_gNB_mui++, size, (unsigned char *const)buffer, rrc_deliver_dl_rrc_message, &data); + deliver_dl_rrc_message_data_t data = {.rrc = rrc, .dl_rrc = &dl_rrc, .assoc_id = ue_data.du_assoc_id}; + nr_pdcp_data_req_srb(ue_p->rrc_ue_id, + srb_id, + rrc_gNB_mui++, + size, + (unsigned char *const)buffer, + rrc_deliver_dl_rrc_message, + &data); } static int get_dl_band(const f1ap_served_cell_info_t *cell_info) @@ -189,9 +198,13 @@ static int get_dl_bw(const f1ap_served_cell_info_t *cell_info) static int get_ssb_arfcn(const f1ap_served_cell_info_t *cell_info, const NR_MIB_t *mib, const NR_SIB1_t *sib1) { DevAssert(cell_info != NULL && sib1 != NULL && mib != NULL); - const NR_FrequencyInfoDL_SIB_t* freq_info = &sib1->servingCellConfigCommon->downlinkConfigCommon.frequencyInfoDL; - AssertFatal(freq_info->scs_SpecificCarrierList.list.count == 1, "cannot handle more than one carrier, but has %d\n", freq_info->scs_SpecificCarrierList.list.count); - AssertFatal(freq_info->scs_SpecificCarrierList.list.array[0]->offsetToCarrier == 0, "cannot handle offsetToCarrier != 0, but is %ld\n", freq_info->scs_SpecificCarrierList.list.array[0]->offsetToCarrier); + const NR_FrequencyInfoDL_SIB_t *freq_info = &sib1->servingCellConfigCommon->downlinkConfigCommon.frequencyInfoDL; + AssertFatal(freq_info->scs_SpecificCarrierList.list.count == 1, + "cannot handle more than one carrier, but has %d\n", + freq_info->scs_SpecificCarrierList.list.count); + AssertFatal(freq_info->scs_SpecificCarrierList.list.array[0]->offsetToCarrier == 0, + "cannot handle offsetToCarrier != 0, but is %ld\n", + freq_info->scs_SpecificCarrierList.list.array[0]->offsetToCarrier); long offsetToPointA = freq_info->offsetToPointA; long kssb = mib->ssb_SubcarrierOffset; @@ -208,16 +221,25 @@ static int get_ssb_arfcn(const f1ap_served_cell_info_t *cell_info, const NR_MIB_ else AssertFatal(false, "Invalid absoluteFrequencyPointA: %d\n", dl_arfcn); - uint64_t freqpointa = from_nrarfcn(band, scs, dl_arfcn); // offsetToPointA and kSSB are both on 15kHz SCS for FR1 and 60kHz SCS for FR2 (see 38.211 sections 7.4.3.1 and 4.4.4.2) // SSB uses the SCS of the cell and is 20 RBs wide, so use 10 - uint64_t freqssb = freqpointa + scaling * 15000 * (offsetToPointA * 12 + kssb) + 10ll * 12 * (1 << scs) * 15000; + uint64_t freqssb = freqpointa + scaling * 15000 * (offsetToPointA * 12 + kssb) + 10ll * 12 * (1 << scs) * 15000; int bw_index = get_supported_band_index(scs, band, get_dl_bw(cell_info)); int band_size_hz = get_supported_bw_mhz(band > 256 ? FR2 : FR1, bw_index) * 1000 * 1000; uint32_t ssb_arfcn = to_nrarfcn(band, freqssb, scs, band_size_hz); - LOG_D(RRC, "freqpointa %ld Hz/%d offsetToPointA %ld kssb %ld scs %d band %d band_size_hz %d freqssb %ld Hz/%d\n", freqpointa, dl_arfcn, offsetToPointA, kssb, scs, band, band_size_hz, freqssb, ssb_arfcn); + LOG_D(NR_RRC, + "freqpointa %ld Hz/%d offsetToPointA %ld kssb %ld scs %d band %d band_size_hz %d freqssb %ld Hz/%d\n", + freqpointa, + dl_arfcn, + offsetToPointA, + kssb, + scs, + band, + band_size_hz, + freqssb, + ssb_arfcn); if (RC.nrmac) { // debugging: let's test this is the correct ARFCN @@ -228,7 +250,11 @@ static int get_ssb_arfcn(const f1ap_served_cell_info_t *cell_info, const NR_MIB_ // taken out (but the reestablishment will likely not work). const NR_ServingCellConfigCommon_t *scc = RC.nrmac[0]->common_channels[0].ServingCellConfigCommon; uint32_t scc_ssb_arfcn = *scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB; - AssertFatal(ssb_arfcn == scc_ssb_arfcn, "mismatch of SCC SSB ARFCN original %d vs. computed %d! Note: you can remove this Assert, the gNB might run but UE connection instable\n", scc_ssb_arfcn, ssb_arfcn); + AssertFatal(ssb_arfcn == scc_ssb_arfcn, + "mismatch of SCC SSB ARFCN original %d vs. computed %d! Note: you can remove this Assert, the gNB might run but UE " + "connection instable\n", + scc_ssb_arfcn, + ssb_arfcn); } return ssb_arfcn; @@ -960,13 +986,11 @@ static void rrc_gNB_generate_RRCReestablishment(rrc_gNB_ue_context_t *ue_context const uint8_t *masterCellGroup_from_DU, const rnti_t old_rnti, const nr_rrc_du_container_t *du) -//----------------------------------------------------------------------------- { module_id_t module_id = 0; gNB_RRC_INST *rrc = RC.nrrrc[module_id]; int enable_ciphering = 0; gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; - uint8_t buffer[RRC_BUF_SIZE] = {0}; uint8_t xid = rrc_gNB_get_next_transaction_identifier(module_id); ue_p->xids[xid] = RRC_REESTABLISH; @@ -985,8 +1009,12 @@ static void rrc_gNB_generate_RRCReestablishment(rrc_gNB_ue_context_t *ue_context nr_derive_key(UP_ENC_ALG, ue_p->ciphering_algorithm, ue_p->kgnb, kUPenc); nr_derive_key(RRC_ENC_ALG, ue_p->ciphering_algorithm, ue_p->kgnb, kRRCenc); nr_derive_key(RRC_INT_ALG, ue_p->integrity_algorithm, ue_p->kgnb, kRRCint); - - LOG_I(NR_RRC, "Set PDCP security UE %d RNTI %04x nca %ld nia %d in RRCReestablishment\n", ue_p->rrc_ue_id, ue_p->rnti, ue_p->ciphering_algorithm, ue_p->integrity_algorithm); + LOG_I(NR_RRC, + "Set PDCP security UE %d RNTI %04x nca %ld nia %d in RRCReestablishment\n", + ue_p->rrc_ue_id, + ue_p->rnti, + ue_p->ciphering_algorithm, + ue_p->integrity_algorithm); uint8_t security_mode = enable_ciphering ? ue_p->ciphering_algorithm | (ue_p->integrity_algorithm << 4) : 0 | (ue_p->integrity_algorithm << 4); @@ -1085,11 +1113,11 @@ static void rrc_gNB_process_RRCReestablishmentComplete(const protocol_ctxt_t *co } //----------------------------------------------------------------------------- -int nr_rrc_reconfiguration_req(rrc_gNB_ue_context_t *const ue_context_pP, - protocol_ctxt_t *const ctxt_pP, - const int dl_bwp_id, - const int ul_bwp_id) { - +int nr_rrc_reconfiguration_req(rrc_gNB_ue_context_t *const ue_context_pP, + protocol_ctxt_t *const ctxt_pP, + const int dl_bwp_id, + const int ul_bwp_id) +{ uint8_t xid = rrc_gNB_get_next_transaction_identifier(ctxt_pP->module_id); gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; ue_p->xids[xid] = RRC_DEDICATED_RECONF; @@ -1112,7 +1140,10 @@ int nr_rrc_reconfiguration_req(rrc_gNB_ue_context_t *const ue_context_pP return 0; } -static void rrc_handle_RRCSetupRequest(gNB_RRC_INST *rrc, sctp_assoc_t assoc_id, const NR_RRCSetupRequest_IEs_t *rrcSetupRequest, const f1ap_initial_ul_rrc_message_t *msg) +static void rrc_handle_RRCSetupRequest(gNB_RRC_INST *rrc, + sctp_assoc_t assoc_id, + const NR_RRCSetupRequest_IEs_t *rrcSetupRequest, + const f1ap_initial_ul_rrc_message_t *msg) { rrc_gNB_ue_context_t *ue_context_p = NULL; if (NR_InitialUE_Identity_PR_randomValue == rrcSetupRequest->ue_Identity.present) { @@ -1189,7 +1220,10 @@ static const char *get_reestab_cause(NR_ReestablishmentCause_t c) return "UNKNOWN Failure (ASN.1 decoder error?)"; } -static void rrc_handle_RRCReestablishmentRequest(gNB_RRC_INST *rrc, sctp_assoc_t assoc_id, const NR_RRCReestablishmentRequest_IEs_t *req, const f1ap_initial_ul_rrc_message_t *msg) +static void rrc_handle_RRCReestablishmentRequest(gNB_RRC_INST *rrc, + sctp_assoc_t assoc_id, + const NR_RRCReestablishmentRequest_IEs_t *req, + const f1ap_initial_ul_rrc_message_t *msg) { uint64_t random_value = 0; const char *scause = get_reestab_cause(req->reestablishmentCause); @@ -1235,9 +1269,7 @@ static void rrc_handle_RRCReestablishmentRequest(gNB_RRC_INST *rrc, sctp_assoc_t // 3GPP TS 38.321 version 15.13.0 Section 7.1 Table 7.1-1: RNTI values if (req->ue_Identity.c_RNTI < 0x1 || req->ue_Identity.c_RNTI > 0xffef) { /* c_RNTI range error should not happen */ - LOG_E(NR_RRC, - "NR_RRCReestablishmentRequest c_RNTI %04lx range error, fallback to RRC setup\n", - req->ue_Identity.c_RNTI); + LOG_E(NR_RRC, "NR_RRCReestablishmentRequest c_RNTI %04lx range error, fallback to RRC setup\n", req->ue_Identity.c_RNTI); goto fallback_rrc_setup; } @@ -1300,9 +1332,7 @@ static int handle_rrcReestablishmentComplete(const protocol_ctxt_t *const ctxt_p DevAssert(reestablishment_complete->criticalExtensions.present == NR_RRCReestablishmentComplete__criticalExtensions_PR_rrcReestablishmentComplete); - rrc_gNB_process_RRCReestablishmentComplete(ctxt_pP, - ue_context_p, - reestablishment_complete->rrc_TransactionIdentifier); + rrc_gNB_process_RRCReestablishmentComplete(ctxt_pP, ue_context_p, reestablishment_complete->rrc_TransactionIdentifier); UE->ue_reestablishment_counter++; return 0; @@ -2069,7 +2099,7 @@ void rrc_gNB_process_e1_bearer_context_setup_resp(e1ap_bearer_setup_resp_t *resp resp->gNB_cu_up_ue_id); // save the tunnel address for the PDU sessions - for (int i=0; i < resp->numPDUSessions; i++) { + for (int i = 0; i < resp->numPDUSessions; i++) { pdu_session_setup_t *e1_pdu = &resp->pduSession[i]; rrc_pdu_session_param_t *rrc_pdu = find_pduSession(UE, e1_pdu->id, false); if (rrc_pdu == NULL) { @@ -2178,7 +2208,7 @@ void rrc_gNB_process_e1_bearer_context_setup_resp(e1ap_bearer_setup_resp_t *resp /** * @brief E1AP Bearer Context Modification Response processing on CU-CP -*/ + */ void rrc_gNB_process_e1_bearer_context_modif_resp(const e1ap_bearer_modif_resp_t *resp) { gNB_RRC_INST *rrc = RC.nrrrc[0]; @@ -2197,7 +2227,7 @@ void rrc_gNB_process_e1_bearer_context_modif_resp(const e1ap_bearer_modif_resp_t /** * @brief E1AP Bearer Context Release processing -*/ + */ void rrc_gNB_process_e1_bearer_context_release_cplt(const e1ap_bearer_release_cplt_t *cplt) { // there is not really anything to do here as of now @@ -2364,6 +2394,7 @@ void *rrc_gnb_task(void *args_p) { break; /* Messages from PDCP */ + /* From DU -> CU */ case F1AP_UL_RRC_MESSAGE: PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, instance, From 06c2ce1777ef17d7de6383b92f4a5df96ccf8c42 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 8 Feb 2024 20:24:48 +0100 Subject: [PATCH 09/10] E1 Sabox test: shorten ping --- ci-scripts/xml_files/container_sa_e1_b200_quectel.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ci-scripts/xml_files/container_sa_e1_b200_quectel.xml b/ci-scripts/xml_files/container_sa_e1_b200_quectel.xml index 41358c1022..5bed6b88ba 100644 --- a/ci-scripts/xml_files/container_sa_e1_b200_quectel.xml +++ b/ci-scripts/xml_files/container_sa_e1_b200_quectel.xml @@ -114,9 +114,9 @@ Ping - Ping: 20pings in 20sec + Ping: 50pings in 10sec idefix - -c 20 %cn_ip% + -c 20 -i 0.2 %cn_ip% 1 25 From 60447a24a1dff7139e049714f4bd393a696a3b59 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 8 Feb 2024 20:24:37 +0100 Subject: [PATCH 10/10] E1: add reestablishment test --- .../container_sa_e1_b200_quectel.xml | 25 +++++++++++++++++++ .../sa_e1_b200_gnb/docker-compose.yml | 10 ++++++-- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/ci-scripts/xml_files/container_sa_e1_b200_quectel.xml b/ci-scripts/xml_files/container_sa_e1_b200_quectel.xml index 5bed6b88ba..541edb9172 100644 --- a/ci-scripts/xml_files/container_sa_e1_b200_quectel.xml +++ b/ci-scripts/xml_files/container_sa_e1_b200_quectel.xml @@ -37,6 +37,10 @@ 370001 370000 370002 + 360001 + 100002 + 360002 + 350000 310011 310002 330201 @@ -152,6 +156,27 @@ single-ue + + Custom_Command + Trigger Reestablishment (on DU) + ofqot + echo ci force_reestab | nc -N 192.168.68.195 9090 | grep -E 'Reset RLC counters of UE RNTI [0-9a-f]{4} to trigger reestablishment' + yes + + + Custom_Command + Verify Reestablishment (on CU) + ofqot + echo ci get_reestab_count | nc -N 192.168.68.194 9090 | grep -E 'UE RNTI [0-9a-f]{4} reestab 1' + yes + + + + IdleSleep + Sleep + 10 + + Undeploy_Object Undeploy CU-DU diff --git a/ci-scripts/yaml_files/sa_e1_b200_gnb/docker-compose.yml b/ci-scripts/yaml_files/sa_e1_b200_gnb/docker-compose.yml index 8e353b945e..132f73fb3c 100644 --- a/ci-scripts/yaml_files/sa_e1_b200_gnb/docker-compose.yml +++ b/ci-scripts/yaml_files/sa_e1_b200_gnb/docker-compose.yml @@ -6,7 +6,7 @@ services: privileged: true container_name: sa-cucp-gnb environment: - USE_ADDITIONAL_OPTIONS: --sa --log_config.global_log_options level,nocolor,time,line_num,function + USE_ADDITIONAL_OPTIONS: --sa --telnetsrv --telnetsrv.shrmod ci --log_config.global_log_options level,nocolor,time,line_num,function volumes: - ../../conf_files/gnb-cucp.sa.f1.quectel.conf:/opt/oai-gnb/etc/gnb.conf networks: @@ -43,7 +43,13 @@ services: container_name: sa-du-b200-gnb environment: USE_B2XX: 'yes' - USE_ADDITIONAL_OPTIONS: --sa --RUs.[0].sdr_addrs serial=30C51D4 --continuous-tx -E --log_config.global_log_options level,nocolor,time,line_num,function --gNBs.[0].min_rxtxtime 2 --gNBs.[0].do_CSIRS 1 --gNBs.[0].do_SRS 1 --RUs.[0].att_rx 18 --RUs.[0].att_tx 18 + USE_ADDITIONAL_OPTIONS: --sa + --RUs.[0].sdr_addrs serial=30C51D4 + --continuous-tx -E + --telnetsrv --telnetsrv.shrmod ci + --gNBs.[0].min_rxtxtime 2 --gNBs.[0].do_CSIRS 1 --gNBs.[0].do_SRS 1 + --RUs.[0].att_rx 18 --RUs.[0].att_tx 18 + --log_config.global_log_options level,nocolor,time,line_num,function volumes: - ../../conf_files/gnb-du.sa.band78.106prb.usrpb200.conf:/opt/oai-gnb/etc/gnb.conf - /dev:/dev