From 5dd9ead820615b64aa15f911e5fa41dae79f1aa6 Mon Sep 17 00:00:00 2001 From: Eduard Vlad Date: Thu, 22 May 2025 15:10:40 +0200 Subject: [PATCH 01/35] DL NAS Transport: Fix Message Type retrieval on too short message The change addresses the SM message type retrieval for DL NAS Transport messages. The assumption of an offset 17 = 7 (MM Sec) + 3 (MM Plain) + 1 (IEI) + 2 (Len) + 4 (SM) is correct. However, if the DL NAS Transport is received in a plain header, the lengths would not add up anymore. (This is not complying with the standard, so not allowed, but possible). The check for the length is necessary to not process arbitrary memory contents beyond the `pdu_buffer`. Signed-off-by: Eduard Vlad --- openair3/NAS/NR_UE/nr_nas_msg.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/openair3/NAS/NR_UE/nr_nas_msg.c b/openair3/NAS/NR_UE/nr_nas_msg.c index b1378c3360..74e5498663 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg.c +++ b/openair3/NAS/NR_UE/nr_nas_msg.c @@ -1202,6 +1202,10 @@ static void handle_pdu_session_accept(uint8_t *pdu_buffer, uint32_t msg_length, */ void handleDownlinkNASTransport(uint8_t * pdu_buffer, int pdu_length, int instance) { + if (pdu_length < 17) { + LOG_E(NAS, "Received DL NAS Transport message too short (%d)\n", pdu_length); + return; + } uint8_t msg_type = *(pdu_buffer + 16); if (msg_type == FGS_PDU_SESSION_ESTABLISHMENT_ACC) { LOG_A(NAS, "Received PDU Session Establishment Accept in DL NAS Transport\n"); From a7e2374e1d66cb767e372e9d22f8bee9838e4c05 Mon Sep 17 00:00:00 2001 From: Eduard Vlad Date: Thu, 22 May 2025 15:26:23 +0200 Subject: [PATCH 02/35] NAS Registration Reject: Add bounds and lengths checks This change adds lengths checks to the received registration reject message and also performs a bounds check for the received cause. Since the cause is not checked, any string in the memory can be dereferenced, possibly leading to DoS. Signed-off-by: Eduard Vlad --- openair3/NAS/NR_UE/nr_nas_msg.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/openair3/NAS/NR_UE/nr_nas_msg.c b/openair3/NAS/NR_UE/nr_nas_msg.c index b1378c3360..e62cf12e3b 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg.c +++ b/openair3/NAS/NR_UE/nr_nas_msg.c @@ -32,6 +32,7 @@ #include "nr_nas_msg.h" #include #include "NR_NAS_defs.h" +#include #include #include #include @@ -1798,10 +1799,23 @@ void *nas_nrue(void *args_p) case FGS_PDU_SESSION_ESTABLISHMENT_REJ: LOG_E(NAS, "Received PDU Session Establishment reject\n"); break; - case FGS_REGISTRATION_REJECT: - LOG_E(NAS, "Received Registration reject cause: %s\n", cause_text_info[pdu_buffer[17]].text); + case FGS_REGISTRATION_REJECT: { + + if (pdu_length < 18) { + LOG_E(NAS, "Received Registration reject message too short\n"); + break; + } + + uint8_t cause = pdu_buffer[17]; + if (cause >= sizeof(cause_text_info) / sizeof(cause_text_info[0])) { + LOG_E(NAS, "Received Registration reject cause %d unknown\n", cause); + break; + } + + LOG_E(NAS, "Received Registration reject cause: %s\n", cause_text_info[cause].text); exit(1); break; + } case FGS_SERVICE_ACCEPT: { byte_array_t buffer = {.buf = pdu_buffer, .len = pdu_length}; handle_service_accept(nas, &buffer); From 61d5dd0094231090812698cc3d01bfdadd7ce1ca Mon Sep 17 00:00:00 2001 From: Raghavendra Dinavahi Date: Tue, 8 Apr 2025 12:03:34 +0200 Subject: [PATCH 03/35] GNB-Changes: Enabling ulsyncvalidityDuration timer in SIB19 ntn-UlSyncValidityDuration in SIB19 from Spec 38.331 v17.12 A validity duration configured by the network for assistance information which indicates the maximum time duration (from epochTime) during which the UE can apply assistance information without having acquired new assistance information. The unit of ntn-UlSyncValidityDuration is second. Value s5 corresponds to 5 s, value s10 indicate 10 s and so on. ntn-UlSyncValidityDuration-r17 ENUMERATED{ s5, s10, s15, s20, s25, s30, s35,s40, s45, s50, s55, s60, s120, s180, s240, s900} Implementation of epochtime is under discussion. It can be configured in configuration file according to the above enumeration. For GEO - 240s, MEO - 20s, LEO-5s can be used. --- openair2/GNB_APP/RRC_nr_paramsvalues.h | 2 ++ openair2/GNB_APP/gnb_config.c | 48 ++++++++++++++++++++++++-- 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/openair2/GNB_APP/RRC_nr_paramsvalues.h b/openair2/GNB_APP/RRC_nr_paramsvalues.h index c7b74be8b0..44774342e5 100644 --- a/openair2/GNB_APP/RRC_nr_paramsvalues.h +++ b/openair2/GNB_APP/RRC_nr_paramsvalues.h @@ -124,6 +124,7 @@ #define GNB_CONFIG_STRING_NROFUPLINKSYMBOLS2 "nrofUplinkSymbols2" #define GNB_CONFIG_STRING_SSPBCHBLOCKPOWER "ssPBCH_BlockPower" +#define GNB_CONFIG_STRING_ULSYNCVALIDITYDURATION "ntn-UlSyncValidityDuration-r17" #define GNB_CONFIG_STRING_CELLSPECIFICKOFFSET "cellSpecificKoffset_r17" #define GNB_CONFIG_STRING_EPHEMERIS_POSITION_X "positionX-r17" #define GNB_CONFIG_STRING_EPHEMERIS_POSITION_Y "positionY-r17" @@ -250,6 +251,7 @@ {GNB_CONFIG_STRING_NROFUPLINKSLOTS,NULL,0,.i64ptr=&scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots,.defint64val=2,TYPE_INT64,0},\ {GNB_CONFIG_STRING_NROFUPLINKSYMBOLS,NULL,0,.i64ptr=&scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols,.defint64val=4,TYPE_INT64,0},\ {GNB_CONFIG_STRING_SSPBCHBLOCKPOWER,NULL,0,.i64ptr=&scc->ss_PBCH_BlockPower,.defint64val=20,TYPE_INT64,0}, \ +{GNB_CONFIG_STRING_ULSYNCVALIDITYDURATION,NULL,0,.i64ptr=scc->ext2->ntn_Config_r17->ntn_UlSyncValidityDuration_r17,.defint64val=0,TYPE_INT64,0}, \ {GNB_CONFIG_STRING_CELLSPECIFICKOFFSET,NULL,0,.i64ptr=scc->ext2->ntn_Config_r17->cellSpecificKoffset_r17,.defint64val=0,TYPE_INT64,0}, \ {GNB_CONFIG_STRING_EPHEMERIS_POSITION_X,NULL,0,.i64ptr=&scc->ext2->ntn_Config_r17->ephemerisInfo_r17->choice.positionVelocity_r17->positionX_r17,.defint64val=LONG_MAX,TYPE_INT64,0}, \ {GNB_CONFIG_STRING_EPHEMERIS_POSITION_Y,NULL,0,.i64ptr=&scc->ext2->ntn_Config_r17->ephemerisInfo_r17->choice.positionVelocity_r17->positionY_r17,.defint64val=LONG_MAX,TYPE_INT64,0}, \ diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 2c82a6eb6e..dc9ae7b8e6 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -217,6 +217,7 @@ void prepare_scc(NR_ServingCellConfigCommon_t *scc) scc->ext2 = calloc_or_fail(1, sizeof(*scc->ext2)); scc->ext2->ntn_Config_r17 = calloc_or_fail(1, sizeof(*scc->ext2->ntn_Config_r17)); + scc->ext2->ntn_Config_r17->ntn_UlSyncValidityDuration_r17 = calloc_or_fail(1, sizeof(long)); scc->ext2->ntn_Config_r17->cellSpecificKoffset_r17 = calloc_or_fail(1, sizeof(*scc->ext2->ntn_Config_r17->cellSpecificKoffset_r17)); scc->ext2->ntn_Config_r17->ephemerisInfo_r17 = calloc_or_fail(1, sizeof(*scc->ext2->ntn_Config_r17->ephemerisInfo_r17)); @@ -466,6 +467,40 @@ static void fix_tdd_pattern(NR_ServingCellConfigCommon_t *scc) } } +static int get_ulsyncvalidityduration_enum_value(int val) +{ + int retval = -1; + + switch (val) { + case 5: + case 10: + case 15: + case 20: + case 25: + case 30: + case 35: + case 40: + case 45: + case 50: + case 55: + retval = val / 5 - 1; + break; + case 60: + case 120: + case 180: + case 240: + retval = 10 + val / 60; + break; + case 900: + retval = 15; + break; + default: + AssertFatal(1 == 0, "ulsyncvalidityDuration in SIB19 set to invalid value in Conf file\n"); + break; + } + return retval; +} + void fix_scc(NR_ServingCellConfigCommon_t *scc, uint64_t ssbmap) { scc->ssb_PositionsInBurst->present = get_ssb_len(scc); @@ -573,6 +608,13 @@ void fix_scc(NR_ServingCellConfigCommon_t *scc, uint64_t ssbmap) AssertFatal(*scc->uplinkConfigCommon->initialUplinkBWP->pucch_ConfigCommon->choice.setup->pucch_ResourceCommon < 2, "pucch_ResourceConfig should be 0 or 1 for now\n"); + if (*scc->ext2->ntn_Config_r17->ntn_UlSyncValidityDuration_r17 == 0) { + free(scc->ext2->ntn_Config_r17->ntn_UlSyncValidityDuration_r17); + scc->ext2->ntn_Config_r17->ntn_UlSyncValidityDuration_r17 = NULL; + } else { + int val = get_ulsyncvalidityduration_enum_value(*scc->ext2->ntn_Config_r17->ntn_UlSyncValidityDuration_r17); + *scc->ext2->ntn_Config_r17->ntn_UlSyncValidityDuration_r17 = val; + } if (*scc->ext2->ntn_Config_r17->cellSpecificKoffset_r17 == 0) { free(scc->ext2->ntn_Config_r17->cellSpecificKoffset_r17); scc->ext2->ntn_Config_r17->cellSpecificKoffset_r17 = NULL; @@ -597,8 +639,10 @@ void fix_scc(NR_ServingCellConfigCommon_t *scc, uint64_t ssbmap) scc->ext2->ntn_Config_r17->ephemerisInfo_r17 = NULL; } - if (!scc->ext2->ntn_Config_r17->cellSpecificKoffset_r17 && !scc->ext2->ntn_Config_r17->ta_Info_r17 - && !scc->ext2->ntn_Config_r17->ephemerisInfo_r17) { + if (!scc->ext2->ntn_Config_r17->ntn_UlSyncValidityDuration_r17 && + !scc->ext2->ntn_Config_r17->cellSpecificKoffset_r17 && + !scc->ext2->ntn_Config_r17->ta_Info_r17 && + !scc->ext2->ntn_Config_r17->ephemerisInfo_r17) { free(scc->ext2->ntn_Config_r17); free(scc->ext2); scc->ext2 = NULL; From bc1844b482bad88b1138b112d8288dbe75ea9a56 Mon Sep 17 00:00:00 2001 From: Raghavendra Dinavahi Date: Fri, 9 May 2025 15:02:13 +0200 Subject: [PATCH 04/35] Added in the Conf file for testing in CI, description updated --- ci-scripts/conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn.conf | 2 ++ doc/RUNMODEM.md | 3 +++ 2 files changed, 5 insertions(+) diff --git a/ci-scripts/conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn.conf b/ci-scripts/conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn.conf index 3e7dd08474..fa1bcc20c8 100644 --- a/ci-scripts/conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn.conf +++ b/ci-scripts/conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn.conf @@ -149,6 +149,8 @@ gNBs = #ext2 #ntn_Config_r17 + # This can be of values {s5, s10, s15, s20, s25, s30, s35, s40, s45, s50, s55, s60, s120, s180, s240, s900} + ntn-UlSyncValidityDuration-r17 = 240; cellSpecificKoffset_r17 = 478; ta-Common-r17 = 58629666; # 238.74 ms positionX-r17 = 0; diff --git a/doc/RUNMODEM.md b/doc/RUNMODEM.md index f2e71390c7..ba2d48be28 100644 --- a/doc/RUNMODEM.md +++ b/doc/RUNMODEM.md @@ -231,6 +231,9 @@ Or by providing this the the command line parameters: The main parameters to cope with the large NTN propagation delay are cellSpecificKoffset, ta-Common, ta-CommonDrift and the ephemeris data (satellite position and velocity vectors). +The parameter `ntn-UlSyncValidityDuration-r17` indicates the maximum time duration from epochtime during which the UE can apply assistance information without having acquired new assistance information. i.e this enables UE to re-read SIB19 before timer with value ulSyncValidityDuration expires. The unit of the field is in seconds. Example values for GEO: 240s, MEO: 20s, LEO: 5s. +As epochtime is not implemented yet, UE starts the timer from the TTI where SIB19 is received with ntn-UlSyncValidityDuration-r17 IE. + The parameter `cellSpecificKoffset_r17` is the scheduling offset used for the timing relationships that are modified for NTN (see TS 38.213). The unit of the field Koffset is number of slots for a given subcarrier spacing of 15 kHz. From 171f1fc0151445469d5ecd9fc1c3c28c2bb76d54 Mon Sep 17 00:00:00 2001 From: Bartosz Podrygajlo Date: Wed, 6 Nov 2024 15:10:39 +0100 Subject: [PATCH 05/35] Add ccache and CPM cache in ubuntu22 image builds --- docker/Dockerfile.base.ubuntu22 | 1 + docker/Dockerfile.build.ubuntu22 | 12 ++++++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/docker/Dockerfile.base.ubuntu22 b/docker/Dockerfile.base.ubuntu22 index 60e2aad8ab..5bddb3f88f 100644 --- a/docker/Dockerfile.base.ubuntu22 +++ b/docker/Dockerfile.base.ubuntu22 @@ -40,6 +40,7 @@ RUN apt-get update && \ DEBIAN_FRONTEND=noninteractive apt-get install --yes \ #gcc needed for build_oai build-essential \ + ccache \ psmisc \ git \ #use gcc-12 to avoid problems of default gcc-11 in FlexRIC diff --git a/docker/Dockerfile.build.ubuntu22 b/docker/Dockerfile.build.ubuntu22 index c0de631c41..2f394e247b 100644 --- a/docker/Dockerfile.build.ubuntu22 +++ b/docker/Dockerfile.build.ubuntu22 @@ -36,7 +36,12 @@ WORKDIR /oai-ran COPY . . # build all targets so final targets can be created afterwards -RUN /bin/sh oaienv && \ +RUN \ + # Mount CCache cache direrctory + --mount=type=cache,target=/root/.cache/ccache/ \ + # Mount CPM package cache + --mount=type=cache,target=/root/.cache/cpm/ \ + /bin/sh oaienv && \ cd cmake_targets && \ mkdir -p log && \ ./build_oai -c --ninja \ @@ -54,7 +59,10 @@ RUN /bin/sh oaienv && \ ldd ran_build/build/*.so ## Build FlexRIC for SM Models -RUN mkdir -p openair2/E2AP/flexric/build && \ +RUN \ + # Mount CCache cache direrctory + --mount=type=cache,target=/root/.cache/ccache/ \ + mkdir -p openair2/E2AP/flexric/build && \ cd openair2/E2AP/flexric/build && \ cmake -GNinja -DCMAKE_BUILD_TYPE=Release \ -DXAPP_MULTILANGUAGE=OFF \ From 8be33ed66f8760e9d051d02f26f51c464c8f9a60 Mon Sep 17 00:00:00 2001 From: Bartosz Podrygajlo Date: Thu, 29 May 2025 15:10:23 +0200 Subject: [PATCH 06/35] Make ubuntu22 base image docker cache friendly Use wget instead of ADD to allow efficient caching of tini install. --- docker/Dockerfile.base.ubuntu22 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docker/Dockerfile.base.ubuntu22 b/docker/Dockerfile.base.ubuntu22 index 5bddb3f88f..ba8707d4db 100644 --- a/docker/Dockerfile.base.ubuntu22 +++ b/docker/Dockerfile.base.ubuntu22 @@ -53,15 +53,15 @@ RUN apt-get update && \ flex \ m4 \ # python3-pip for conf template generation - python3-pip && \ + python3-pip \ + wget && \ update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-12 100 --slave /usr/bin/g++ g++ /usr/bin/g++-12 && \ pip3 install --ignore-installed pyyaml # Add "Tini - A tiny but valid init for containers", https://github.com/krallin/tini # it will be copied into target containers, to print exit numbers and handle signals properly ENV TINI_VERSION=v0.19.0 -ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini-${TARGETARCH} /tini -RUN chmod +x /tini +RUN wget https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini-${TARGETARCH} -O /tini && chmod +x /tini # In some network environments, GIT proxy is required RUN /bin/bash -c "if [[ -v NEEDED_GIT_PROXY ]]; then git config --global http.proxy $NEEDED_GIT_PROXY; fi" From e3e516e65247f42949b82caa28e8e3a50e298968 Mon Sep 17 00:00:00 2001 From: francescomani Date: Thu, 25 Jan 2024 18:57:19 +0100 Subject: [PATCH 07/35] Reception of RRC Setup as response to re-establishment request It also introduces state for resume request (even if not yet implemented) --- openair2/LAYER2/NR_MAC_UE/config_ue.c | 4 ++ openair2/LAYER2/NR_MAC_UE/mac_defs.h | 3 +- openair2/LAYER2/NR_MAC_UE/main_ue_nr.c | 2 +- openair2/RRC/NR_UE/rrc_UE.c | 63 +++++++++++++++++++++++--- openair2/RRC/NR_UE/rrc_defs.h | 1 + 5 files changed, 65 insertions(+), 8 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index 3a5d5e5640..a9825a4de9 100644 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -1718,6 +1718,10 @@ void nr_rrc_mac_config_req_reset(module_id_t module_id, NR_UE_MAC_reset_cause_t sync_req.ssb_bw_scan = false; nr_ue_send_synch_request(mac, module_id, 0, &sync_req); break; + case RRC_SETUP_REESTAB_RESUME: + release_mac_configuration(mac, cause); + nr_ue_mac_default_configs(mac); + break; default: AssertFatal(false, "Invalid MAC reset cause %d\n", cause); } diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index b3ca280f86..7925e9b755 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -196,7 +196,8 @@ typedef enum { GO_TO_IDLE, DETACH, T300_EXPIRY, - RE_ESTABLISHMENT + RE_ESTABLISHMENT, + RRC_SETUP_REESTAB_RESUME, } NR_UE_MAC_reset_cause_t; typedef struct { diff --git a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c index 6a6c7633bf..e189d7dcf9 100644 --- a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c +++ b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c @@ -271,7 +271,7 @@ void release_mac_configuration(NR_UE_MAC_INST_t *mac, NR_UE_MAC_reset_cause_t ca // in case of re-establishment we don't need to release initial BWP config common int first_bwp_rel = 0; // first BWP to release - if (cause == RE_ESTABLISHMENT) { + if (cause == RE_ESTABLISHMENT || cause == RRC_SETUP_REESTAB_RESUME) { first_bwp_rel = 1; // release dedicated BWP0 config NR_UE_DL_BWP_t *bwp = mac->dl_BWPs.array[0]; diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 4abc712507..d36a1ca485 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -1138,16 +1138,64 @@ static void rrc_ue_generate_RRCSetupComplete(const NR_UE_RRC_INST_t *rrc, const nr_pdcp_data_req_srb(rrc->ue_id, srb_id, 0, size, buffer, deliver_pdu_srb_rlc, NULL); } +static void nr_rrc_rrcsetup_fallback(NR_UE_RRC_INST_t *rrc) +{ + LOG_W(NR_RRC, + "[UE %ld] Recived RRCSetup in response to %s request\n", + rrc->ue_id, rrc->ra_trigger == RRC_CONNECTION_REESTABLISHMENT ? "RRCReestablishment" : "RRCResume"); + + // discard any stored UE Inactive AS context and suspendConfig + // TODO + + // discard any current AS security context including + // K_RRCenc key, the K_RRCint key, the K_UPint key and the K_UPenc key + // TODO only kgnb is stored + memset(rrc->kgnb, 0, sizeof(rrc->kgnb)); + rrc->as_security_activated = false; + + // release radio resources for all established RBs except SRB0, + // including release of the RLC entities, of the associated PDCP entities and of SDAP + for (int i = 1; i <= MAX_DRBS_PER_UE; i++) { + if (get_DRB_status(rrc, i) != RB_NOT_PRESENT) { + set_DRB_status(rrc, i, RB_NOT_PRESENT); + nr_pdcp_release_drb(rrc->ue_id, i); + } + } + for (int i = 1; i < NR_NUM_SRB; i++) { + if (rrc->Srb[i] != RB_NOT_PRESENT) { + rrc->Srb[i] = RB_NOT_PRESENT; + nr_pdcp_release_srb(rrc->ue_id, i); + } + } + for (int i = 1; i < NR_MAX_NUM_LCID; i++) { + if (rrc->active_RLC_entity[i]) { + rrc->active_RLC_entity[i] = false; + nr_rlc_release_entity(rrc->ue_id, i); + } + } + nr_sdap_delete_ue_entities(rrc->ue_id); + + // release the RRC configuration except for the default L1 parameter values, + // default MAC Cell Group configuration and CCCH configuration + // TODO to be completed + NR_UE_MAC_reset_cause_t cause = RRC_SETUP_REESTAB_RESUME; + MessageDef *msg = itti_alloc_new_message(TASK_RRC_NRUE, 0, NR_MAC_RRC_CONFIG_RESET); + NR_MAC_RRC_CONFIG_RESET(msg).cause = cause; + itti_send_msg_to_task(TASK_MAC_UE, rrc->ue_id, msg); + + // indicate to upper layers fallback of the RRC connection + // TODO + + // stop timer T380, if running + // TODO not implemented yet +} + static void nr_rrc_process_rrcsetup(NR_UE_RRC_INST_t *rrc, const NR_RRCSetup_t *rrcSetup) { // if the RRCSetup is received in response to an RRCReestablishmentRequest // or RRCResumeRequest or RRCResumeRequest1 - // TODO none of the procedures implemented yet - if (rrc->ra_trigger == RRC_CONNECTION_REESTABLISHMENT) { - LOG_E(NR_RRC, "Handling of RRCSetup in response of RRCReestablishment not implemented yet. Going back to IDLE.\n"); - nr_rrc_going_to_IDLE(rrc, OTHER, NULL); - return; - } + if (rrc->ra_trigger == RRC_CONNECTION_REESTABLISHMENT || rrc->ra_trigger == RRC_RESUME_REQUEST) + nr_rrc_rrcsetup_fallback(rrc); // perform the cell group configuration procedure in accordance with the received masterCellGroup nr_rrc_ue_process_masterCellGroup(rrc, @@ -1177,6 +1225,9 @@ static void nr_rrc_process_rrcsetup(NR_UE_RRC_INST_t *rrc, const NR_RRCSetup_t * MessageDef *msg_p = itti_alloc_new_message(TASK_RRC_NRUE, 0, NR_NAS_CONN_ESTABLISH_IND); itti_send_msg_to_task(TASK_NAS_NRUE, rrc->ue_id, msg_p); + // resetting the RA trigger state after receiving MSG4 with RRCSetup + rrc->ra_trigger = RA_NOT_RUNNING; + // set the content of RRCSetupComplete message // TODO procedues described in 5.3.3.4 seems more complex than what we actualy do rrc_ue_generate_RRCSetupComplete(rrc, rrcSetup->rrc_TransactionIdentifier); diff --git a/openair2/RRC/NR_UE/rrc_defs.h b/openair2/RRC/NR_UE/rrc_defs.h index e428c4c160..9c8b205083 100644 --- a/openair2/RRC/NR_UE/rrc_defs.h +++ b/openair2/RRC/NR_UE/rrc_defs.h @@ -94,6 +94,7 @@ typedef enum RA_trigger_e { RA_NOT_RUNNING, RRC_CONNECTION_SETUP, RRC_CONNECTION_REESTABLISHMENT, + RRC_RESUME_REQUEST, DURING_HANDOVER, NON_SYNCHRONISED, TRANSITION_FROM_RRC_INACTIVE, From cad681e626081e24d9f7cae69e55414b9ca67e36 Mon Sep 17 00:00:00 2001 From: francescomani Date: Thu, 12 Jun 2025 18:43:24 +0200 Subject: [PATCH 08/35] renaming structure for LCID to RB mapping --- openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c | 28 +++++++++++----------- openair2/LAYER2/nr_rlc/nr_rlc_ue_manager.h | 12 +++++----- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c index 8dfa57f92b..88c8d5d377 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c @@ -77,10 +77,10 @@ static uint64_t get_nr_rlc_current_time(void) static void release_rlc_entity_from_lcid(nr_rlc_ue_t *ue, logical_chan_id_t channel_id) { AssertFatal(channel_id != 0, "LCID = 0 shouldn't be handled here\n"); - nr_rlc_rb_t *rb = &ue->lcid2rb[channel_id - 1]; - if (rb->type == NR_RLC_NONE) + nr_lcid_rb_t *rb = &ue->lcid2rb[channel_id - 1]; + if (rb->type == NR_LCID_NONE) return; - if (rb->type == NR_RLC_SRB) { + if (rb->type == NR_LCID_SRB) { int id = rb->choice.srb_id - 1; AssertFatal(id >= 0, "logic bug: impossible to have srb0 here\n"); if (ue->srb[id]) { @@ -91,7 +91,7 @@ static void release_rlc_entity_from_lcid(nr_rlc_ue_t *ue, logical_chan_id_t chan LOG_E(RLC, "Trying to release a non-established enity with LCID %d\n", channel_id); } else { - AssertFatal(rb->type == NR_RLC_DRB, + AssertFatal(rb->type == NR_LCID_DRB, "Invalid RB type\n"); int id = rb->choice.drb_id - 1; if (ue->drb[id]) { @@ -108,14 +108,14 @@ logical_chan_id_t nr_rlc_get_lcid_from_rb(int ue_id, bool is_srb, int rb_id) nr_rlc_manager_lock(nr_rlc_ue_manager); nr_rlc_ue_t *ue = nr_rlc_manager_get_ue(nr_rlc_ue_manager, ue_id); for (logical_chan_id_t id = 1; id <= 32; id++) { - nr_rlc_rb_t *rb = &ue->lcid2rb[id - 1]; + nr_lcid_rb_t *rb = &ue->lcid2rb[id - 1]; if (is_srb) { - if (rb->type == NR_RLC_SRB && rb->choice.srb_id == rb_id) { + if (rb->type == NR_LCID_SRB && rb->choice.srb_id == rb_id) { nr_rlc_manager_unlock(nr_rlc_ue_manager); return id; } } else { - if (rb->type == NR_RLC_DRB && rb->choice.drb_id == rb_id) { + if (rb->type == NR_LCID_DRB && rb->choice.drb_id == rb_id) { nr_rlc_manager_unlock(nr_rlc_ue_manager); return id; } @@ -130,14 +130,14 @@ static nr_rlc_entity_t *get_rlc_entity_from_lcid(nr_rlc_ue_t *ue, logical_chan_i { if (channel_id == 0) return ue->srb0; - nr_rlc_rb_t *rb = &ue->lcid2rb[channel_id - 1]; - if (rb->type == NR_RLC_NONE) + nr_lcid_rb_t *rb = &ue->lcid2rb[channel_id - 1]; + if (rb->type == NR_LCID_NONE) return NULL; - if (rb->type == NR_RLC_SRB) { + if (rb->type == NR_LCID_SRB) { AssertFatal(rb->choice.srb_id > 0, "logic bug: impossible to have srb0 here\n"); return ue->srb[rb->choice.srb_id - 1]; } else { - AssertFatal(rb->type == NR_RLC_DRB, + AssertFatal(rb->type == NR_LCID_DRB, "Invalid RB type\n"); return ue->drb[rb->choice.drb_id - 1]; } @@ -698,7 +698,7 @@ void nr_rlc_add_srb(int ue_id, int srb_id, const NR_RLC_BearerConfig_t *rlc_Bear NR_RLC_BearerConfig__servedRadioBearer_PR_srb_Identity), "servedRadioBearer for SRB mandatory present when setting up an SRB RLC entity\n"); int local_id = rlc_BearerConfig->logicalChannelIdentity - 1; // LCID 0 for SRB 0 not mapped - ue->lcid2rb[local_id].type = NR_RLC_SRB; + ue->lcid2rb[local_id].type = NR_LCID_SRB; ue->lcid2rb[local_id].choice.srb_id = rlc_BearerConfig->servedRadioBearer->choice.srb_Identity; if (ue->srb[srb_id-1] != NULL) { LOG_E(RLC, "SRB %d already exists for UE %d, do nothing\n", srb_id, ue_id); @@ -763,7 +763,7 @@ static void add_drb_am(int ue_id, int drb_id, const NR_RLC_BearerConfig_t *rlc_B NR_RLC_BearerConfig__servedRadioBearer_PR_drb_Identity), "servedRadioBearer for DRB mandatory present when setting up an SRB RLC entity\n"); int local_id = rlc_BearerConfig->logicalChannelIdentity - 1; // LCID 0 for SRB 0 not mapped - ue->lcid2rb[local_id].type = NR_RLC_DRB; + ue->lcid2rb[local_id].type = NR_LCID_DRB; ue->lcid2rb[local_id].choice.drb_id = rlc_BearerConfig->servedRadioBearer->choice.drb_Identity; if (ue->drb[drb_id-1] != NULL) { LOG_E(RLC, "DRB %d already exists for UE %d, do nothing\n", drb_id, ue_id); @@ -818,7 +818,7 @@ static void add_drb_um(int ue_id, int drb_id, const NR_RLC_BearerConfig_t *rlc_B NR_RLC_BearerConfig__servedRadioBearer_PR_drb_Identity), "servedRadioBearer for DRB mandatory present when setting up an SRB RLC entity\n"); int local_id = rlc_BearerConfig->logicalChannelIdentity - 1; // LCID 0 for SRB 0 not mapped - ue->lcid2rb[local_id].type = NR_RLC_DRB; + ue->lcid2rb[local_id].type = NR_LCID_DRB; ue->lcid2rb[local_id].choice.drb_id = rlc_BearerConfig->servedRadioBearer->choice.drb_Identity; if (ue->drb[drb_id-1] != NULL) { LOG_E(RLC, "DEBUG add_drb_um: warning DRB %d already exist for ue %d, do nothing\n", drb_id, ue_id); diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_ue_manager.h b/openair2/LAYER2/nr_rlc/nr_rlc_ue_manager.h index 3dec237958..9a4288f192 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_ue_manager.h +++ b/openair2/LAYER2/nr_rlc/nr_rlc_ue_manager.h @@ -28,21 +28,21 @@ typedef void nr_rlc_ue_manager_t; -typedef enum nr_rlc_rb_type { NR_RLC_NONE = 0, NR_RLC_SRB = 1, NR_RLC_DRB = 2 } nr_rlc_rb_type; - typedef enum { NR_RLC_OP_MODE_SPLIT_GNB, NR_RLC_OP_MODE_MONO_GNB, NR_RLC_OP_MODE_UE, } nr_rlc_op_mode_t; -typedef struct nr_rlc_rb_t { - nr_rlc_rb_type type; +typedef enum nr_lcid_rb_type { NR_LCID_NONE = 0, NR_LCID_SRB = 1, NR_LCID_DRB = 2 } nr_lcid_rb_type; + +typedef struct nr_lcid_rb_t { + nr_lcid_rb_type type; union { int srb_id; int drb_id; } choice; -} nr_rlc_rb_t; +} nr_lcid_rb_t; typedef void (*rlf_handler_t)(int rnti); @@ -51,7 +51,7 @@ typedef struct nr_rlc_ue_t { nr_rlc_entity_t *srb0; nr_rlc_entity_t *srb[3]; nr_rlc_entity_t *drb[MAX_DRBS_PER_UE]; - nr_rlc_rb_t lcid2rb[32]; + nr_lcid_rb_t lcid2rb[32]; rlf_handler_t rlf_handler; } nr_rlc_ue_t; From f2e06a8b12f93eeb69a1f1fef2a41d4d0ec9e7dd Mon Sep 17 00:00:00 2001 From: francescomani Date: Thu, 12 Jun 2025 19:30:09 +0200 Subject: [PATCH 09/35] store RB information in LCID structure at UE --- common/platform_types.h | 10 +++++ openair2/LAYER2/NR_MAC_UE/config_ue.c | 46 +++++++++++++++------- openair2/LAYER2/NR_MAC_UE/mac_defs.h | 1 + openair2/LAYER2/nr_rlc/nr_rlc_ue_manager.h | 10 ----- 4 files changed, 43 insertions(+), 24 deletions(-) diff --git a/common/platform_types.h b/common/platform_types.h index 8cbd502fda..e345288061 100644 --- a/common/platform_types.h +++ b/common/platform_types.h @@ -207,6 +207,16 @@ typedef struct nsa_msg_t { uint8_t msg_buffer[MAX_MESSAGE_SIZE]; } nsa_msg_t; +typedef enum nr_lcid_rb_type { NR_LCID_NONE = 0, NR_LCID_SRB = 1, NR_LCID_DRB = 2 } nr_lcid_rb_type; + +typedef struct nr_lcid_rb_t { + nr_lcid_rb_type type; + union { + int srb_id; + int drb_id; + } choice; +} nr_lcid_rb_t; + typedef struct transport_layer_addr_s { /** * Transport Layer Address as a bitstring: diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index 3a5d5e5640..626b772e8b 100644 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -811,7 +811,7 @@ static uint32_t get_lc_bucket_size(long prioritisedBitRate, long bucketSizeDurat } // default configuration as per 38.331 section 9.2.1 -static void set_default_logicalchannelconfig(nr_lcordered_info_t *lc_info, NR_SRB_Identity_t srb_id) +static void set_default_logicalchannelconfig(nr_lcordered_info_t *lc_info, int srb_id) { lc_info->lcid = srb_id; lc_info->priority = srb_id == 2 ? 3 : 1; @@ -822,12 +822,13 @@ static void set_default_logicalchannelconfig(nr_lcordered_info_t *lc_info, NR_SR static void nr_configure_lc_config(NR_UE_MAC_INST_t *mac, nr_lcordered_info_t *lc_info, NR_LogicalChannelConfig_t *mac_lc_config, - NR_SRB_Identity_t srb_id) + nr_lcid_rb_t rb) { NR_LC_SCHEDULING_INFO *lc_sched_info = get_scheduling_info_from_lcid(mac, lc_info->lcid); - if (srb_id > 0 && !mac_lc_config->ul_SpecificParameters) { + lc_info->rb = rb; + if (rb.type == NR_LCID_SRB && !mac_lc_config->ul_SpecificParameters) { // release configuration and reset to default - set_default_logicalchannelconfig(lc_info, srb_id); + set_default_logicalchannelconfig(lc_info, rb.choice.srb_id); // invalid LCGID to signal it is absent in the configuration lc_sched_info->LCGID = NR_INVALID_LCGID; return; @@ -848,6 +849,25 @@ static void nr_configure_lc_config(NR_UE_MAC_INST_t *mac, nr_timer_start(bjt); } +static nr_lcid_rb_t configure_lcid_rb(NR_RLC_BearerConfig_t *rlc_bearer) +{ + nr_lcid_rb_t rb; + if (rlc_bearer->servedRadioBearer->present == NR_RLC_BearerConfig__servedRadioBearer_PR_srb_Identity) { + rb.type = NR_LCID_SRB; + rb.choice.srb_id = rlc_bearer->servedRadioBearer->choice.srb_Identity; + return rb; + } + + if (rlc_bearer->servedRadioBearer->present == NR_RLC_BearerConfig__servedRadioBearer_PR_drb_Identity) { + rb.type = NR_LCID_DRB; + rb.choice.drb_id = rlc_bearer->servedRadioBearer->choice.drb_Identity; + return rb; + } + LOG_E(NR_MAC, "Error. RLC should be linked to either DRB or SRB.\n"); + rb.type = NR_LCID_NONE; + return rb; +} + static void configure_logicalChannelBearer(NR_UE_MAC_INST_t *mac, struct NR_CellGroupConfig__rlc_BearerToAddModList *rlc_toadd_list, struct NR_CellGroupConfig__rlc_BearerToReleaseList *rlc_torelease_list) @@ -870,6 +890,9 @@ static void configure_logicalChannelBearer(NR_UE_MAC_INST_t *mac, if (rlc_toadd_list) { for (int i = 0; i < rlc_toadd_list->list.count; i++) { NR_RLC_BearerConfig_t *rlc_bearer = rlc_toadd_list->list.array[i]; + nr_lcid_rb_t rb = configure_lcid_rb(rlc_bearer); + if (rb.type == NR_LCID_NONE) + continue; int lc_identity = rlc_bearer->logicalChannelIdentity; NR_LogicalChannelConfig_t *mac_lc_config = rlc_bearer->mac_LogicalChannelConfig; int j; @@ -879,14 +902,9 @@ static void configure_logicalChannelBearer(NR_UE_MAC_INST_t *mac, } if (j < mac->lc_ordered_list.count) { LOG_D(NR_MAC, "Logical channel %d is already established, Reconfiguring now\n", lc_identity); - if (mac_lc_config != NULL) { - NR_SRB_Identity_t srb_id = 0; - if (rlc_bearer->servedRadioBearer->present == NR_RLC_BearerConfig__servedRadioBearer_PR_srb_Identity) - srb_id = rlc_bearer->servedRadioBearer->choice.srb_Identity; - nr_configure_lc_config(mac, mac->lc_ordered_list.array[j], mac_lc_config, srb_id); - } - } - else { + if (mac_lc_config != NULL) + nr_configure_lc_config(mac, mac->lc_ordered_list.array[j], mac_lc_config, rb); + } else { /* setup of new LCID*/ nr_lcordered_info_t *lc_info = calloc(1, sizeof(*lc_info)); lc_info->lcid = lc_identity; @@ -895,12 +913,12 @@ static void configure_logicalChannelBearer(NR_UE_MAC_INST_t *mac, if (rlc_bearer->servedRadioBearer->present == NR_RLC_BearerConfig__servedRadioBearer_PR_srb_Identity) { /* SRB */ NR_SRB_Identity_t srb_id = rlc_bearer->servedRadioBearer->choice.srb_Identity; if (mac_lc_config != NULL) - nr_configure_lc_config(mac, lc_info, mac_lc_config, srb_id); + nr_configure_lc_config(mac, lc_info, mac_lc_config, rb); else set_default_logicalchannelconfig(lc_info, srb_id); } else { /* DRB */ AssertFatal(mac_lc_config, "When establishing a DRB, LogicalChannelConfig should be mandatorily present\n"); - nr_configure_lc_config(mac, lc_info, mac_lc_config, 0); + nr_configure_lc_config(mac, lc_info, mac_lc_config, rb); } ASN_SEQUENCE_ADD(&mac->lc_ordered_list, lc_info); } diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index b3ca280f86..24b82ecf51 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -450,6 +450,7 @@ typedef struct nr_lcordered_info_s { uint32_t bucket_size; bool sr_DelayTimerApplied; bool lc_SRMask; + nr_lcid_rb_t rb; } nr_lcordered_info_t; typedef struct { diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_ue_manager.h b/openair2/LAYER2/nr_rlc/nr_rlc_ue_manager.h index 9a4288f192..67484e7108 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_ue_manager.h +++ b/openair2/LAYER2/nr_rlc/nr_rlc_ue_manager.h @@ -34,16 +34,6 @@ typedef enum { NR_RLC_OP_MODE_UE, } nr_rlc_op_mode_t; -typedef enum nr_lcid_rb_type { NR_LCID_NONE = 0, NR_LCID_SRB = 1, NR_LCID_DRB = 2 } nr_lcid_rb_type; - -typedef struct nr_lcid_rb_t { - nr_lcid_rb_type type; - union { - int srb_id; - int drb_id; - } choice; -} nr_lcid_rb_t; - typedef void (*rlf_handler_t)(int rnti); typedef struct nr_rlc_ue_t { From cce685323a5ab52a516496e5d3596f7b01a78116 Mon Sep 17 00:00:00 2001 From: francescomani Date: Sun, 15 Jun 2025 17:38:45 +0200 Subject: [PATCH 10/35] adding RNTI information to stats printed at UE --- openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c index 0d0829181e..0f3466e0df 100644 --- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c @@ -90,7 +90,14 @@ void print_ue_mac_stats(const module_id_t mod, const int frame_rx, const int slo if (nbdl < 1) nbdl = 1; - cur += snprintf(cur, end - cur, "UE %d stats sfn: %d.%d, cumulated bad DCI %d\n", mod, frame_rx, slot_rx, mac->stats.bad_dci); + cur += snprintf(cur, + end - cur, + "UE %d RNTI %04x stats sfn: %d.%d, cumulated bad DCI %d\n", + mod, + mac->crnti, + frame_rx, + slot_rx, + mac->stats.bad_dci); cur += snprintf(cur, end - cur, " DL harq: %lu", mac->stats.dl.rounds[0]); int nb; From 38bac5376bc32e6f6c53314adb3ec4a4d318527a Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 16 Jun 2025 10:13:20 +0200 Subject: [PATCH 11/35] fix in multi-UE RFsim action description --- ci-scripts/xml_files/container_5g_rfsim.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci-scripts/xml_files/container_5g_rfsim.xml b/ci-scripts/xml_files/container_5g_rfsim.xml index f20820629b..80e4d189ff 100644 --- a/ci-scripts/xml_files/container_5g_rfsim.xml +++ b/ci-scripts/xml_files/container_5g_rfsim.xml @@ -242,7 +242,7 @@ Detach_UE - Detach OAI UE 2 to 10 + Detach OAI UE 3 to 10 rfsim5g_ue3 rfsim5g_ue4 rfsim5g_ue5 rfsim5g_ue6 rfsim5g_ue7 rfsim5g_ue8 rfsim5g_ue9 rfsim5g_ue10 cacofonix cacofonix cacofonix cacofonix cacofonix cacofonix cacofonix cacofonix From a41be56b2a80b54a0e153f519b9f3bacec3c12fc Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Thu, 12 Jun 2025 18:09:19 +0200 Subject: [PATCH 12/35] USRP lib: fix incorrect config check for time_source fallback Corrected a logic bug in usrp_lib.cpp where the code mistakenly checked openair0_cfg[0].clock_source instead of time_source when a time_source was already specified in usrp_args. Also improved the warning log to clarify that the config value is being ignored in favor of the explicit user-provided usrp_args. Co-authored-by: Alexandre Serio --- radio/USRP/usrp_lib.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/radio/USRP/usrp_lib.cpp b/radio/USRP/usrp_lib.cpp index 8fbb561149..6dde70b2eb 100644 --- a/radio/USRP/usrp_lib.cpp +++ b/radio/USRP/usrp_lib.cpp @@ -1202,9 +1202,9 @@ extern "C" { } } else { - if (openair0_cfg[0].clock_source != unset) { - LOG_W(HW,"Time source set in both usrp_args and in time_source, ingnoring the latter!\n"); - } + if (openair0_cfg[0].time_source != unset) { + LOG_W(HW, "Time source set in both usrp_args and in openair0_cfg[0].time_source, ignoring the latter!\n"); + } } From 3331a43b95c02800c83b47d2e2d4fcb89ac0a5b6 Mon Sep 17 00:00:00 2001 From: francescomani Date: Fri, 13 Jun 2025 10:49:22 +0200 Subject: [PATCH 13/35] add option to suspend/resume RBs at MAC upon signaling from RRC --- openair2/COMMON/rrc_messages_def.h | 1 + openair2/COMMON/rrc_messages_types.h | 6 ++++++ openair2/LAYER2/NR_MAC_UE/config_ue.c | 20 ++++++++++++++++++++ openair2/LAYER2/NR_MAC_UE/mac_defs.h | 1 + openair2/LAYER2/NR_MAC_UE/mac_proto.h | 2 +- openair2/RRC/NR_UE/L2_interface_ue.c | 3 +++ openair2/RRC/NR_UE/rrc_UE.c | 18 ++++++++++++++++-- 7 files changed, 48 insertions(+), 3 deletions(-) diff --git a/openair2/COMMON/rrc_messages_def.h b/openair2/COMMON/rrc_messages_def.h index 67aadb2869..df295e2011 100644 --- a/openair2/COMMON/rrc_messages_def.h +++ b/openair2/COMMON/rrc_messages_def.h @@ -88,6 +88,7 @@ MESSAGE_DEF(NRRRC_FRAME_PROCESS, MESSAGE_PRIORITY_MED, NRRrcFramePr // UE: RRC -> MAC messages MESSAGE_DEF(NR_MAC_RRC_CONFIG_RESET, MESSAGE_PRIORITY_MED, nr_mac_rrc_config_reset_t, nr_mac_rrc_config_reset) MESSAGE_DEF(NR_MAC_RRC_CONFIG_CG, MESSAGE_PRIORITY_MED, nr_mac_rrc_config_cg_t, nr_mac_rrc_config_cg) +MESSAGE_DEF(NR_MAC_RRC_RESUME_RB, MESSAGE_PRIORITY_MED, nr_mac_rrc_resume_rb_t, nr_mac_rrc_resume_rb) MESSAGE_DEF(NR_MAC_RRC_CONFIG_MIB, MESSAGE_PRIORITY_MED, nr_mac_rrc_config_mib_t, nr_mac_rrc_config_mib) MESSAGE_DEF(NR_MAC_RRC_CONFIG_SIB1, MESSAGE_PRIORITY_MED, nr_mac_rrc_config_sib1_t, nr_mac_rrc_config_sib1) MESSAGE_DEF(NR_MAC_RRC_CONFIG_OTHER_SIB, MESSAGE_PRIORITY_MED, nr_mac_rrc_config_other_sib_t, nr_mac_rrc_config_other_sib) diff --git a/openair2/COMMON/rrc_messages_types.h b/openair2/COMMON/rrc_messages_types.h index a3db7ebba6..094fd0fa40 100644 --- a/openair2/COMMON/rrc_messages_types.h +++ b/openair2/COMMON/rrc_messages_types.h @@ -107,6 +107,7 @@ #define NAS_PDU_SESSION_REQ(mSGpTR) (mSGpTR)->ittiMsg.nas_pdu_session_req #define NR_MAC_RRC_CONFIG_RESET(mSGpTR) (mSGpTR)->ittiMsg.nr_mac_rrc_config_reset #define NR_MAC_RRC_CONFIG_CG(mSGpTR) (mSGpTR)->ittiMsg.nr_mac_rrc_config_cg +#define NR_MAC_RRC_RESUME_RB(mSGpTR) (mSGpTR)->ittiMsg.nr_mac_rrc_resume_rb #define NR_MAC_RRC_CONFIG_MIB(mSGpTR) (mSGpTR)->ittiMsg.nr_mac_rrc_config_mib #define NR_MAC_RRC_CONFIG_SIB1(mSGpTR) (mSGpTR)->ittiMsg.nr_mac_rrc_config_sib1 #define NR_MAC_RRC_CONFIG_OTHER_SIB(mSGpTR) (mSGpTR)->ittiMsg.nr_mac_rrc_config_other_sib @@ -470,6 +471,11 @@ typedef struct { int ue_id; } RlcMaxRtxIndication; +typedef struct { + bool is_srb; + int rb_id; +} nr_mac_rrc_resume_rb_t; + typedef struct { NR_ReestablishmentCause_t cause; } nr_mac_rrc_config_reset_t; diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index 626b772e8b..7583ee3eb7 100644 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -826,6 +826,7 @@ static void nr_configure_lc_config(NR_UE_MAC_INST_t *mac, { NR_LC_SCHEDULING_INFO *lc_sched_info = get_scheduling_info_from_lcid(mac, lc_info->lcid); lc_info->rb = rb; + lc_info->rb_suspended = false; if (rb.type == NR_LCID_SRB && !mac_lc_config->ul_SpecificParameters) { // release configuration and reset to default set_default_logicalchannelconfig(lc_info, rb.choice.srb_id); @@ -1729,6 +1730,13 @@ void nr_rrc_mac_config_req_reset(module_id_t module_id, NR_UE_MAC_reset_cause_t nr_ue_mac_default_configs(mac); nr_ue_reset_sync_state(mac); release_mac_configuration(mac, cause); + // suspend all RBs except SRB0 + for (int j = 0; j < mac->lc_ordered_list.count; j++) { + nr_lcordered_info_t *lc = mac->lc_ordered_list.array[j]; + if (lc->rb.type == NR_LCID_SRB && lc->rb.choice.srb_id == 0) + continue; + lc->rb_suspended = true; + } // apply the timeAlignmentTimerCommon included in SIB1 configure_timeAlignmentTimer(&mac->time_alignment_timer, mac->timeAlignmentTimerCommon, mac->current_UL_BWP->scs); // new sync with old cell ID (re-establishment on the same cell) @@ -1743,6 +1751,18 @@ void nr_rrc_mac_config_req_reset(module_id_t module_id, NR_UE_MAC_reset_cause_t AssertFatal(!ret, "mutex failed %d\n", ret); } +void nr_rrc_mac_resume_rb(module_id_t module_id, bool is_srb, int rb_id) +{ + NR_UE_MAC_INST_t *mac = get_mac_inst(module_id); + for (int j = 0; j < mac->lc_ordered_list.count; j++) { + nr_lcordered_info_t *lc = mac->lc_ordered_list.array[j]; + if (is_srb && lc->rb.type == NR_LCID_SRB && lc->rb.choice.srb_id == rb_id) + lc->rb_suspended = false; + if (!is_srb && lc->rb.type == NR_LCID_DRB && lc->rb.choice.drb_id == rb_id) + lc->rb_suspended = false; + } +} + static void configure_si_schedulingInfo(NR_UE_MAC_INST_t *mac, NR_SI_SchedulingInfo_t *si_SchedulingInfo, NR_SI_SchedulingInfo_v1700_t *si_SchedulingInfo_v1700) diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index 24b82ecf51..bd6cab17be 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -451,6 +451,7 @@ typedef struct nr_lcordered_info_s { bool sr_DelayTimerApplied; bool lc_SRMask; nr_lcid_rb_t rb; + bool rb_suspended; } nr_lcordered_info_t; typedef struct { diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index b058f6e681..cdc07c2ca2 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -93,7 +93,7 @@ void nr_rrc_mac_config_req_sib1(module_id_t module_id, int cc_idP, NR_SIB1_t *si struct position; /* forward declaration */ void nr_rrc_mac_config_other_sib(module_id_t module_id, NR_SIB19_r17_t *sib19_r17, bool can_start_ra); - +void nr_rrc_mac_resume_rb(module_id_t module_id, bool is_srb, int rb_id); void nr_rrc_mac_config_req_reset(module_id_t module_id, NR_UE_MAC_reset_cause_t cause); /**\brief initialization NR UE MAC instance(s)*/ diff --git a/openair2/RRC/NR_UE/L2_interface_ue.c b/openair2/RRC/NR_UE/L2_interface_ue.c index 09bce459f2..fe2eb2cfed 100644 --- a/openair2/RRC/NR_UE/L2_interface_ue.c +++ b/openair2/RRC/NR_UE/L2_interface_ue.c @@ -146,6 +146,9 @@ void process_msg_rcc_to_mac(MessageDef *msg) bool can_start_ra = NR_MAC_RRC_CONFIG_OTHER_SIB(msg).can_start_ra; nr_rrc_mac_config_other_sib(ue_id, NR_MAC_RRC_CONFIG_OTHER_SIB(msg).sib19, can_start_ra); } break; + case NR_MAC_RRC_RESUME_RB: + nr_rrc_mac_resume_rb(ue_id, NR_MAC_RRC_RESUME_RB(msg).is_srb, NR_MAC_RRC_RESUME_RB(msg).rb_id); + break; default: LOG_E(NR_MAC, "Unexpected msg from RRC: %d\n", ITTI_MSG_ID(msg)); } diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index bb58191e24..4fa5d58cf9 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -894,6 +894,10 @@ static void nr_rrc_handle_msg3_indication(NR_UE_RRC_INST_t *rrc, rnti_t rnti) nr_rlc_reconfigure_entity(rrc->ue_id, lc_id, NULL); // resume SRB1 rrc->Srb[srb_id] = RB_ESTABLISHED; + MessageDef *msg = itti_alloc_new_message(TASK_RRC_NRUE, 0, NR_MAC_RRC_RESUME_RB); + NR_MAC_RRC_RESUME_RB(msg).is_srb = true; + NR_MAC_RRC_RESUME_RB(msg).rb_id = 1; + itti_send_msg_to_task(TASK_MAC_UE, rrc->ue_id, msg); break; case DURING_HANDOVER: AssertFatal(1==0, "ra_trigger not implemented yet!\n"); @@ -1868,11 +1872,21 @@ static int nr_rrc_ue_decode_dcch(NR_UE_RRC_INST_t *rrc, if (rrc->reconfig_after_reestab) { // if this is the first RRCReconfiguration message after successful completion of the RRC re-establishment procedure // resume SRB2 and DRBs that are suspended - if (rrc->Srb[2] == RB_SUSPENDED) + if (rrc->Srb[2] == RB_SUSPENDED) { rrc->Srb[2] = RB_ESTABLISHED; + MessageDef *msg = itti_alloc_new_message(TASK_RRC_NRUE, 0, NR_MAC_RRC_RESUME_RB); + NR_MAC_RRC_RESUME_RB(msg).is_srb = true; + NR_MAC_RRC_RESUME_RB(msg).rb_id = 2; + itti_send_msg_to_task(TASK_MAC_UE, rrc->ue_id, msg); + } for (int i = 1; i <= MAX_DRBS_PER_UE; i++) { - if (get_DRB_status(rrc, i) == RB_SUSPENDED) + if (get_DRB_status(rrc, i) == RB_SUSPENDED) { set_DRB_status(rrc, i, RB_ESTABLISHED); + MessageDef *msg = itti_alloc_new_message(TASK_RRC_NRUE, 0, NR_MAC_RRC_RESUME_RB); + NR_MAC_RRC_RESUME_RB(msg).is_srb = false; + NR_MAC_RRC_RESUME_RB(msg).rb_id = i; + itti_send_msg_to_task(TASK_MAC_UE, rrc->ue_id, msg); + } } rrc->reconfig_after_reestab = false; } From 2b4b3fcd00237e4dd073462016b11c99fcb4ac85 Mon Sep 17 00:00:00 2001 From: francescomani Date: Fri, 13 Jun 2025 11:40:28 +0200 Subject: [PATCH 14/35] discard rx PDU if RB is suspended --- openair2/LAYER2/NR_MAC_UE/config_ue.c | 11 +++++++++++ openair2/LAYER2/NR_MAC_UE/mac_proto.h | 2 +- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 11 ++++++++--- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index 7583ee3eb7..e74b1a1dc3 100644 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -1751,6 +1751,17 @@ void nr_rrc_mac_config_req_reset(module_id_t module_id, NR_UE_MAC_reset_cause_t AssertFatal(!ret, "mutex failed %d\n", ret); } +bool is_lcid_suspended(NR_UE_MAC_INST_t *mac, int lcid) +{ + for (int j = 0; j < mac->lc_ordered_list.count; j++) { + nr_lcordered_info_t *lc = mac->lc_ordered_list.array[j]; + if (lc->lcid == lcid) + return lc->rb_suspended; + } + LOG_E(NR_MAC, "LCID %d not found in the MAC list\n", lcid); + return false; +} + void nr_rrc_mac_resume_rb(module_id_t module_id, bool is_srb, int rb_id) { NR_UE_MAC_INST_t *mac = get_mac_inst(module_id); diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index cdc07c2ca2..76e178ea6a 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -293,7 +293,7 @@ void configure_csi_resource_mapping(fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_c uint32_t bwp_size, uint32_t bwp_start); - +bool is_lcid_suspended(NR_UE_MAC_INST_t *mac, int lcid); void nr_ra_contention_resolution_failed(NR_UE_MAC_INST_t *mac); void nr_ra_succeeded(NR_UE_MAC_INST_t *mac, const uint8_t gNB_index, const frame_t frame, const int slot); void nr_ra_backoff_setting(RA_config_t *ra); diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 5d3102c07d..f88f574fe0 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -3734,7 +3734,7 @@ void nr_ue_process_mac_pdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_i LOG_D(MAC, "[UE] LCID %d, PDU length %d\n", rx_lcid, pdu_len); bool ret; - switch(rx_lcid){ + switch (rx_lcid) { // MAC CE case DL_SCH_LCID_CCCH: // MSG4 RRC Setup 38.331 @@ -3871,6 +3871,11 @@ void nr_ue_process_mac_pdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_i case 1 ... 32: if (!get_mac_len(pduP, pdu_len, &mac_len, &mac_subheader_len)) return; + // discard the received subPDU if RB is suspended + if (is_lcid_suspended(mac, rx_lcid)) { + LOG_W(NR_MAC, "Received PDU for a suspended RB, corresponding to LCID %d. Dropping it.\n", rx_lcid); + break; + } LOG_D(NR_MAC, "%4d.%2d : DLSCH -> LCID %d %d bytes\n", frameP, slot, rx_lcid, mac_len); nr_mac_rlc_data_ind(mac->ue_id, mac->ue_id, false, rx_lcid, (char *)(pduP + mac_subheader_len), mac_len); break; @@ -3878,8 +3883,8 @@ void nr_ue_process_mac_pdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_i LOG_W(MAC, "unknown lcid %02x\n", rx_lcid); break; } - pduP += ( mac_subheader_len + mac_len ); - pdu_len -= ( mac_subheader_len + mac_len ); + pduP += (mac_subheader_len + mac_len); + pdu_len -= (mac_subheader_len + mac_len); if (pdu_len < 0) LOG_E(MAC, "[UE %d][%d.%d] nr_ue_process_mac_pdu, residual mac pdu length %d < 0!\n", mac->ue_id, frameP, slot, pdu_len); } From 29029677409191213cac02d339a3416470c9f1b2 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 16 Jun 2025 19:01:20 +0200 Subject: [PATCH 15/35] Remove useless sleep in CI footer creation --- ci-scripts/cls_oai_html.py | 1 - 1 file changed, 1 deletion(-) diff --git a/ci-scripts/cls_oai_html.py b/ci-scripts/cls_oai_html.py index 478cbd1860..c90b01a338 100644 --- a/ci-scripts/cls_oai_html.py +++ b/ci-scripts/cls_oai_html.py @@ -224,7 +224,6 @@ class HTMLManagement(): self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.close() - time.sleep(1) if passStatus: cmd = "sed -i -e 's/__STATE_" + self.htmlTabNames[0] + "__//' test_results.html" subprocess.run(cmd, shell=True) From 65f85d55db0955c246b8f45e4acd42c181539c0b Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 17 Jun 2025 08:07:41 +0200 Subject: [PATCH 16/35] Correct b2xx_fx3_utils path on nepes --- ci-scripts/xml_files/container_nsa_b200_quectel.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ci-scripts/xml_files/container_nsa_b200_quectel.xml b/ci-scripts/xml_files/container_nsa_b200_quectel.xml index 035163f3db..17c8a9b14f 100644 --- a/ci-scripts/xml_files/container_nsa_b200_quectel.xml +++ b/ci-scripts/xml_files/container_nsa_b200_quectel.xml @@ -70,9 +70,9 @@ Custom_Command - Reset USRP + Reset USRP on nepes nepes - sudo -S /usr/lib/uhd/utils/b2xx_fx3_utils --reset-device + sudo -S /usr/local/lib/uhd/utils/b2xx_fx3_utils --reset-device From bb9fa2c6a00908f07490930a401b16f0b98fd2ba Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 17 Jun 2025 08:11:12 +0200 Subject: [PATCH 17/35] CI: Remove double Custom_Command Step Step 004000 appears double in the XML description. Remove one to avoid that it is executed twice (because the Python code goes through the list of test descriptions and executes all that match the current ID => double if appears twice). --- ci-scripts/xml_files/container_5g_rfsim_tdd_dora.xml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/ci-scripts/xml_files/container_5g_rfsim_tdd_dora.xml b/ci-scripts/xml_files/container_5g_rfsim_tdd_dora.xml index bf71fc98ab..34d46cc87d 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_tdd_dora.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_tdd_dora.xml @@ -108,14 +108,6 @@ 0 - - Custom_Command - true - Clean-Up any residual volume - cacofonix - docker volume rm 5g_rfsimulator_tdd_dora_rrc.config - - Clean_Test_Server_Images true From 499cdc62d9893f18d6a3dcefad4e0c2604382c9b Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 16 Jun 2025 16:42:05 +0200 Subject: [PATCH 18/35] do not transmit data for a logical channel corresponding to a radio bearer that is suspended --- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index b810bf8de6..87ea607c84 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -1266,10 +1266,11 @@ static void nr_update_rlc_buffers_status(NR_UE_MAC_INST_t *mac, frame_t frameP, { for (int i = 0; i < mac->lc_ordered_list.count; i++) { nr_lcordered_info_t *lc_info = mac->lc_ordered_list.array[i]; + if (lc_info->rb_suspended) + continue; int lcid = lc_info->lcid; NR_LC_SCHEDULING_INFO *lc_sched_info = get_scheduling_info_from_lcid(mac, lcid); mac_rlc_status_resp_t rlc_status = nr_mac_rlc_status_ind(mac->ue_id, frameP, lcid); - if (rlc_status.bytes_in_buffer > 0) { LOG_D(NR_MAC, "[UE %d] LCID %d has %d bytes to transmit at sfn %d.%d\n", @@ -2553,6 +2554,8 @@ static bool fill_mac_sdu(NR_UE_MAC_INST_t *mac, lcid_remain_buffer, lcid); + if (is_lcid_suspended(mac, lcid)) + return false; if (mac_ce_p->end_for_tailer - mac_ce_p->cur_ptr < sizeof(NR_MAC_SUBHEADER_LONG)) // We can't add one byte after the header return false; From d8c7123a8a6afb3cf2f163a446e0a0c177f9f021 Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 17 Jun 2025 09:32:46 +0200 Subject: [PATCH 19/35] preventing segfault in DLInformationTransfer at RRC UE --- openair2/RRC/NR_UE/rrc_UE.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index bb58191e24..ce3082ab95 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -1907,22 +1907,22 @@ static int nr_rrc_ue_decode_dcch(NR_UE_RRC_INST_t *rrc, break; case NR_DL_DCCH_MessageType__c1_PR_dlInformationTransfer: { - NR_DLInformationTransfer_t *dlInformationTransfer = c1->choice.dlInformationTransfer; + NR_DLInformationTransfer_t *dlInfo = c1->choice.dlInformationTransfer; - if (dlInformationTransfer->criticalExtensions.present - == NR_DLInformationTransfer__criticalExtensions_PR_dlInformationTransfer) { + if (dlInfo->criticalExtensions.present == NR_DLInformationTransfer__criticalExtensions_PR_dlInformationTransfer) { + NR_DLInformationTransfer_IEs_t *dlInfo_IE = dlInfo->criticalExtensions.choice.dlInformationTransfer; /* This message hold a dedicated info NAS payload, forward it to NAS */ - NR_DedicatedNAS_Message_t *dedicatedNAS_Message = - dlInformationTransfer->criticalExtensions.choice.dlInformationTransfer->dedicatedNAS_Message; - - MessageDef *ittiMsg = itti_alloc_new_message(TASK_RRC_NRUE, rrc->ue_id, NAS_DOWNLINK_DATA_IND); - dl_info_transfer_ind_t *msg = &NAS_DOWNLINK_DATA_IND(ittiMsg); - msg->UEid = rrc->ue_id; - msg->nasMsg.length = dedicatedNAS_Message->size; - msg->nasMsg.nas_data = malloc(msg->nasMsg.length); - memcpy(msg->nasMsg.nas_data, dedicatedNAS_Message->buf, msg->nasMsg.length); - itti_send_msg_to_task(TASK_NAS_NRUE, rrc->ue_id, ittiMsg); - dedicatedNAS_Message->buf = NULL; // to keep the buffer, up to NAS to free it + NR_DedicatedNAS_Message_t *dedicatedNAS_Message = dlInfo_IE->dedicatedNAS_Message; + if (dedicatedNAS_Message) { + MessageDef *ittiMsg = itti_alloc_new_message(TASK_RRC_NRUE, rrc->ue_id, NAS_DOWNLINK_DATA_IND); + dl_info_transfer_ind_t *msg = &NAS_DOWNLINK_DATA_IND(ittiMsg); + msg->UEid = rrc->ue_id; + msg->nasMsg.length = dedicatedNAS_Message->size; + msg->nasMsg.nas_data = malloc(msg->nasMsg.length); + memcpy(msg->nasMsg.nas_data, dedicatedNAS_Message->buf, msg->nasMsg.length); + itti_send_msg_to_task(TASK_NAS_NRUE, rrc->ue_id, ittiMsg); + dedicatedNAS_Message->buf = NULL; // to keep the buffer, up to NAS to free it + } } } break; case NR_DL_DCCH_MessageType__c1_PR_mobilityFromNRCommand: From 5a30abc29e4808930dbacb0c0c24b5e80a1555ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BAben=20Soares=20Silva?= Date: Thu, 10 Apr 2025 15:58:14 +0100 Subject: [PATCH 20/35] Finish dump procedure for PARAM.response message Remove unnecessary checks on free_param_response --- nfapi/open-nFAPI/fapi/inc/nr_fapi.h | 3 + nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c | 128 ++++++++++++++++++- 2 files changed, 124 insertions(+), 7 deletions(-) diff --git a/nfapi/open-nFAPI/fapi/inc/nr_fapi.h b/nfapi/open-nFAPI/fapi/inc/nr_fapi.h index e8e645b8cf..ee405792d2 100644 --- a/nfapi/open-nFAPI/fapi/inc/nr_fapi.h +++ b/nfapi/open-nFAPI/fapi/inc/nr_fapi.h @@ -35,6 +35,9 @@ #include "debug.h" #define INDENTED_PRINTF(format, ...) printf("%*s" format, depth * 2, "", ##__VA_ARGS__) +#define INDENTED_GENERIC_PRINT(string, format, ...) INDENTED_PRINTF(string " = " format "\n", ##__VA_ARGS__) +#define INDENTED_TLV_PRINT(tlv_name, tlv) INDENTED_GENERIC_PRINT("(0x%04x) " tlv_name, "0x%02x", tlv.tl.tag, tlv.value) +#define INDENTED_TLV_FORMAT_PRINT(tlv_name, format, tlv) INDENTED_GENERIC_PRINT("(0x%04x) " tlv_name, format, tlv.tl.tag, tlv.value) #define EQ_TLV(_tlv_a, _tlv_b) \ do { \ diff --git a/nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c b/nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c index 1b5e3f0ad8..f4d2a618ec 100644 --- a/nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c +++ b/nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c @@ -398,13 +398,10 @@ void free_param_request(nfapi_nr_param_request_scf_t *msg) void free_param_response(nfapi_nr_param_response_scf_t *msg) { - if (msg->vendor_extension) { - free(msg->vendor_extension); - } + free(msg->vendor_extension); + + free(msg->cell_param.config_tlvs_to_report_list); - if (msg->cell_param.config_tlvs_to_report_list) { - free(msg->cell_param.config_tlvs_to_report_list); - } } void free_config_request(nfapi_nr_config_request_scf_t *msg) @@ -986,11 +983,128 @@ void dump_param_request(const nfapi_nr_param_request_scf_t *msg) void dump_param_response(const nfapi_nr_param_response_scf_t *msg) { int depth = 0; - dump_p5_message_header(&msg->header,depth); + dump_p5_message_header(&msg->header, depth); depth++; INDENTED_PRINTF("Error Code = 0x%02x\n", msg->error_code); INDENTED_PRINTF("Number of TLVs = 0x%02x\n", msg->num_tlv); /* dump all TLVs from each table */ + /* Cell Param */ + const nfapi_nr_cell_param_t *cell_param = &msg->cell_param; + depth++; + INDENTED_TLV_PRINT("Release Capability", cell_param->release_capability); + INDENTED_TLV_PRINT("PHY State", cell_param->phy_state); + INDENTED_TLV_PRINT("Skip Blank Dl Config", cell_param->skip_blank_dl_config); + INDENTED_TLV_PRINT("Skip Blank UL Config", cell_param->skip_blank_ul_config); + INDENTED_TLV_PRINT("NumConfigTLVsToReport", cell_param->num_config_tlvs_to_report); + depth++; + for (int i = 0; i < cell_param->num_config_tlvs_to_report.value; i++) { + const nfapi_uint8_tlv_t *reportedTLV = &cell_param->config_tlvs_to_report_list[i]; + INDENTED_PRINTF("(0x%04x) Reported CONFIG TLV #%d = 0x%02x\n", reportedTLV->tl.tag, i + 1, reportedTLV->value); + } + depth--; + /* Carrier Param */ + const nfapi_nr_carrier_param_t *carrier_param = &msg->carrier_param; + INDENTED_TLV_PRINT("Cyclic Prefix", carrier_param->cyclic_prefix); + INDENTED_TLV_PRINT("Supported SCS DL", carrier_param->supported_subcarrier_spacings_dl); + INDENTED_TLV_PRINT("Supported BW DL", carrier_param->supported_bandwidth_dl); + INDENTED_TLV_PRINT("Supported SCS UL", carrier_param->supported_subcarrier_spacings_ul); + INDENTED_TLV_PRINT("Supported BW UL", carrier_param->supported_bandwidth_ul); + /* PDCCH Param */ + const nfapi_nr_pdcch_param_t *pdcch_param = &msg->pdcch_param; + INDENTED_TLV_PRINT("CCE Mapping Type", pdcch_param->cce_mapping_type); + INDENTED_TLV_PRINT("CSet Outside First 3 OFDM Symbols of Slot", pdcch_param->coreset_outside_first_3_of_ofdm_syms_of_slot); + INDENTED_TLV_PRINT("Precoder Granularity Coreset", pdcch_param->coreset_precoder_granularity_coreset); + INDENTED_TLV_PRINT("PDCCH Mu MIMO", pdcch_param->pdcch_mu_mimo); + INDENTED_TLV_PRINT("PDCCH Precoder Cycling", pdcch_param->pdcch_precoder_cycling); + INDENTED_TLV_PRINT("Max PDCCH per Slot", pdcch_param->max_pdcch_per_slot); + /* PUCHH Params */ + const nfapi_nr_pucch_param_t *pucch_param = &msg->pucch_param; + INDENTED_TLV_PRINT("PUCCH Formats", pucch_param->pucch_formats); + INDENTED_TLV_PRINT("Max PUCCH per Slot", pucch_param->max_pucchs_per_slot); + /* PDSCH Params */ + const nfapi_nr_pdsch_param_t *pdsch_param = &msg->pdsch_param; + INDENTED_TLV_PRINT("PDSCH Mapping Type", pdsch_param->pdsch_mapping_type); + INDENTED_TLV_PRINT("PDSCH Allocation Types", pdsch_param->pdsch_allocation_types); + INDENTED_TLV_PRINT("PDSCH VRB to PRB Mapping", pdsch_param->pdsch_vrb_to_prb_mapping); + INDENTED_TLV_PRINT("PDSCH CBG", pdsch_param->pdsch_cbg); + INDENTED_TLV_PRINT("PDSCH DMRS Config Types", pdsch_param->pdsch_dmrs_config_types); + INDENTED_TLV_PRINT("PDSCH DMRS Max Length", pdsch_param->pdsch_dmrs_max_length); + INDENTED_TLV_PRINT("PDSCH DMRS Additional Position", pdsch_param->pdsch_dmrs_additional_pos); + INDENTED_TLV_PRINT("Max PDSCH TBs per Slot", pdsch_param->max_pdsch_tbs_per_slot); + INDENTED_TLV_PRINT("Max number MIMO Layers PDSCH", pdsch_param->max_number_mimo_layers_pdsch); + INDENTED_TLV_PRINT("Supported Max Modulation Order DL", pdsch_param->supported_max_modulation_order_dl); + INDENTED_TLV_PRINT("Max Mu MIMO Users DL", pdsch_param->max_mu_mimo_users_dl); + INDENTED_TLV_PRINT("PDSCH Data in DMRS Symbols", pdsch_param->pdsch_data_in_dmrs_symbols); + INDENTED_TLV_PRINT("Preemption Support", pdsch_param->premption_support); + INDENTED_TLV_PRINT("PDSCH Non Slot Support", pdsch_param->pdsch_non_slot_support); + /* PUSCH Params */ + const nfapi_nr_pusch_param_t *pusch_param = &msg->pusch_param; + INDENTED_TLV_PRINT("UCI Mux ULSCH in PUSCH", pusch_param->uci_mux_ulsch_in_pusch); + INDENTED_TLV_PRINT("UCI Only PUSCH", pusch_param->uci_only_pusch); + INDENTED_TLV_PRINT("PUSCH Frequency Hopping", pusch_param->pusch_frequency_hopping); + INDENTED_TLV_PRINT("PUSCH DMRS Config Types", pusch_param->pusch_dmrs_config_types); + INDENTED_TLV_PRINT("PUSCH DMRS Max Len", pusch_param->pusch_dmrs_max_len); + INDENTED_TLV_PRINT("PUSCH DMRS Additional Pos", pusch_param->pusch_dmrs_additional_pos); + INDENTED_TLV_PRINT("PUSCH CBG", pusch_param->pusch_cbg); + INDENTED_TLV_PRINT("PUSCH Mapping Type", pusch_param->pusch_mapping_type); + INDENTED_TLV_PRINT("PUSCH Allocation Types", pusch_param->pusch_allocation_types); + INDENTED_TLV_PRINT("PUSCH VRB to PRB Mapping", pusch_param->pusch_vrb_to_prb_mapping); + INDENTED_TLV_PRINT("PUSCH Max PTRS Ports", pusch_param->pusch_max_ptrs_ports); + INDENTED_TLV_PRINT("Max PUSCH TBs per Slot", pusch_param->max_pduschs_tbs_per_slot); + INDENTED_TLV_PRINT("Max Number MIMO Layers non CB PUSCH", pusch_param->max_number_mimo_layers_non_cb_pusch); + INDENTED_TLV_PRINT("Supported Modulation Order UL", pusch_param->supported_modulation_order_ul); + INDENTED_TLV_PRINT("Max MU MIMO Users UL", pusch_param->max_mu_mimo_users_ul); + INDENTED_TLV_PRINT("DTFS OFDM Support", pusch_param->dfts_ofdm_support); + INDENTED_TLV_PRINT("PUSCH Aggregation Factor", pusch_param->pusch_aggregation_factor); + /* PRACH Params */ + const nfapi_nr_prach_param_t *prach_param = &msg->prach_param; + INDENTED_TLV_PRINT("PRACH Long Formats", prach_param->prach_long_formats); + INDENTED_TLV_PRINT("PRACH Short Formats", prach_param->prach_short_formats); + INDENTED_TLV_PRINT("PRACH Restricted Sets", prach_param->prach_restricted_sets); + INDENTED_TLV_PRINT("Max PRACH Occasions in a Slot", prach_param->max_prach_fd_occasions_in_a_slot); + /* Measurement Params */ + const nfapi_nr_measurement_param_t *measurement_param = &msg->measurement_param; + INDENTED_TLV_PRINT("RSSI Measurement Support", measurement_param->rssi_measurement_support); + /* nFAPI Config */ + const nfapi_nr_nfapi_t *nfapi_config = &msg->nfapi_config; + if (nfapi_config->p7_vnf_address_ipv4.tl.tag) { + char ip_str[INET_ADDRSTRLEN]; + INDENTED_GENERIC_PRINT("(0x%04x) P7 VNF Address IPv4", + "%s", + nfapi_config->p7_vnf_address_ipv4.tl.tag, + inet_ntop(AF_INET, nfapi_config->p7_vnf_address_ipv4.address, ip_str, sizeof(ip_str))); + } + if (nfapi_config->p7_vnf_address_ipv6.tl.tag) { + char addr6[INET6_ADDRSTRLEN]; + INDENTED_GENERIC_PRINT("(0x%04x) P7 VNF Address IPv6", + "%s", + nfapi_config->p7_vnf_address_ipv6.tl.tag, + inet_ntop(AF_INET6, nfapi_config->p7_vnf_address_ipv6.address, addr6, sizeof(addr6))); + } + INDENTED_TLV_FORMAT_PRINT("P7 VNF Port", "%d", nfapi_config->p7_vnf_port); + + if (nfapi_config->p7_pnf_address_ipv4.tl.tag) { + char ip_str[INET_ADDRSTRLEN]; + INDENTED_GENERIC_PRINT("(0x%04x) P7 PNF Address IPv4", + "%s", + nfapi_config->p7_pnf_address_ipv4.tl.tag, + inet_ntop(AF_INET, nfapi_config->p7_pnf_address_ipv4.address, ip_str, sizeof(ip_str))); + } + if (nfapi_config->p7_pnf_address_ipv6.tl.tag) { + char addr6[INET6_ADDRSTRLEN]; + INDENTED_GENERIC_PRINT("(0x%04x) P7 PNF Address IPv6", + "%s", + nfapi_config->p7_pnf_address_ipv6.tl.tag, + inet_ntop(AF_INET6, nfapi_config->p7_pnf_address_ipv6.address, addr6, sizeof(addr6))); + } + INDENTED_TLV_FORMAT_PRINT("P7 PNF Port", "%d", nfapi_config->p7_pnf_port); + INDENTED_TLV_FORMAT_PRINT("Timing Window", "%d", nfapi_config->timing_window); + INDENTED_TLV_FORMAT_PRINT("Timing Info Mode", "%d", nfapi_config->timing_info_mode); + INDENTED_TLV_FORMAT_PRINT("Timing Info Period", "%d", nfapi_config->timing_info_period); + INDENTED_TLV_FORMAT_PRINT("DL_TTI Timing Offset", "%d", nfapi_config->dl_tti_timing_offset); + INDENTED_TLV_FORMAT_PRINT("UL_TTI Timing Offset", "%d", nfapi_config->ul_tti_timing_offset); + INDENTED_TLV_FORMAT_PRINT("UL_DCI Timing Offset", "%d", nfapi_config->ul_dci_timing_offset); + INDENTED_TLV_FORMAT_PRINT("TX_DATA Timing Offset", "%d", nfapi_config->tx_data_timing_offset); depth--; } From 5016fc75c6a729596c50d279766213a37e4b1a4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BAben=20Soares=20Silva?= Date: Fri, 11 Apr 2025 14:12:08 +0100 Subject: [PATCH 21/35] Finish dump procedure for CONFIG.request message Remove unnecessary checks on free_config_request Added logic to fill random data for PNF addresses and port TLVs to test dumping function --- nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c | 219 ++++++++++++++++++- nfapi/tests/p5/nr_fapi_config_request_test.c | 15 ++ 2 files changed, 233 insertions(+), 1 deletion(-) diff --git a/nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c b/nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c index f4d2a618ec..52f2ee8031 100644 --- a/nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c +++ b/nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c @@ -1111,10 +1111,227 @@ void dump_param_response(const nfapi_nr_param_response_scf_t *msg) void dump_config_request(const nfapi_nr_config_request_scf_t *msg) { int depth = 0; - dump_p5_message_header(&msg->header,depth); + dump_p5_message_header(&msg->header, depth); depth++; INDENTED_PRINTF("Number of TLVs = 0x%02x\n", msg->num_tlv); /* dump all TLVs from each table */ + /* Carrier Config */ + const nfapi_nr_carrier_config_t *carrier_config = &msg->carrier_config; + INDENTED_TLV_PRINT("DL Bandwidth", carrier_config->dl_bandwidth); + INDENTED_TLV_PRINT("DL Frequency", carrier_config->dl_frequency); + INDENTED_PRINTF("(0x%04x) DL K0 = ", NFAPI_NR_CONFIG_DL_K0_TAG); + for (int i = 0; i < 5; i++) { + printf("%d ", carrier_config->dl_k0[i].value); + } + printf("\n"); + INDENTED_PRINTF("(0x%04x) DL Grid Size = ", NFAPI_NR_CONFIG_DL_GRID_SIZE_TAG); + for (int i = 0; i < 5; i++) { + printf("%d ", carrier_config->dl_grid_size[i].value); + } + printf("\n"); + INDENTED_TLV_PRINT("Num TX Antennas", carrier_config->num_tx_ant); + INDENTED_TLV_PRINT("UL Bandwidth", carrier_config->uplink_bandwidth); + INDENTED_TLV_PRINT("UL Frequency", carrier_config->uplink_frequency); + INDENTED_PRINTF("(0x%04x) UL K0 = ", NFAPI_NR_CONFIG_UL_K0_TAG); + for (int i = 0; i < 5; i++) { + printf("%d ", carrier_config->ul_k0[i].value); + } + printf("\n"); + INDENTED_PRINTF("(0x%04x) UL Grid Size = ", NFAPI_NR_CONFIG_UL_GRID_SIZE_TAG); + for (int i = 0; i < 5; i++) { + printf("%d ", carrier_config->ul_grid_size[i].value); + } + printf("\n"); + INDENTED_TLV_PRINT("Num RX Antennas", carrier_config->num_rx_ant); + INDENTED_TLV_PRINT("Frequency Shift 7p5KHz", carrier_config->frequency_shift_7p5khz); + /* Cell Config */ + const nfapi_nr_cell_config_t *cell_config = &msg->cell_config; + INDENTED_TLV_PRINT("Physical Cell ID", cell_config->phy_cell_id); + INDENTED_TLV_PRINT("Frame Duplex Type", cell_config->frame_duplex_type); + /* SSB Config */ + const nfapi_nr_ssb_config_t *ssb_config = &msg->ssb_config; + INDENTED_TLV_PRINT("SSB Block Power", ssb_config->ss_pbch_power); + INDENTED_TLV_PRINT("BCH Payload", ssb_config->bch_payload); + INDENTED_TLV_PRINT("SCS Common", ssb_config->scs_common); + /* PRACH Config */ + const nfapi_nr_prach_config_t *prach_config = &msg->prach_config; + INDENTED_TLV_PRINT("PRACH Sequence Length", prach_config->prach_sequence_length); + INDENTED_TLV_PRINT("PRACH Subcarrier Spacing", prach_config->prach_sub_c_spacing); + INDENTED_TLV_PRINT("Restricted Set Config", prach_config->restricted_set_config); + INDENTED_TLV_PRINT("Num PRACH FD Occasions", prach_config->num_prach_fd_occasions); + INDENTED_TLV_PRINT("PRACH Config Index", prach_config->prach_ConfigurationIndex); + depth++; + for (int i = 0; i < prach_config->num_prach_fd_occasions.value; i++) { + const nfapi_nr_num_prach_fd_occasions_t *prach_fd_occasion = &(prach_config->num_prach_fd_occasions_list[i]); + INDENTED_TLV_PRINT("PRACH Root Sequence Index", prach_fd_occasion->prach_root_sequence_index); + INDENTED_TLV_PRINT("Num Root Sequences", prach_fd_occasion->num_root_sequences); + INDENTED_TLV_PRINT("K1", prach_fd_occasion->k1); + INDENTED_TLV_PRINT("PRACH Zero CorrelationZone Config", prach_fd_occasion->prach_zero_corr_conf); + INDENTED_TLV_PRINT("Num Unused Root Sequences", prach_fd_occasion->num_unused_root_sequences); + depth++; + for (int k = 0; k < prach_fd_occasion->num_unused_root_sequences.value; k++) { + INDENTED_TLV_PRINT("Unused Root Sequence", prach_fd_occasion->unused_root_sequences_list[k]); + } + depth--; + } + depth--; + INDENTED_TLV_PRINT("SSB Per RACH", prach_config->ssb_per_rach); + INDENTED_TLV_PRINT("PRACH Multiple Carriers in a Band", prach_config->prach_multiple_carriers_in_a_band); + /* SSB Table */ + const nfapi_nr_ssb_table_t *ssb_table = &msg->ssb_table; + INDENTED_TLV_PRINT("SSB Offset PointA", ssb_table->ssb_offset_point_a); + INDENTED_TLV_PRINT("Beta PSS", ssb_table->beta_pss); + INDENTED_TLV_PRINT("SSB Period", ssb_table->ssb_period); + INDENTED_TLV_PRINT("SSB Subcarrier Offset", ssb_table->ssb_subcarrier_offset); + INDENTED_TLV_PRINT("MIB", ssb_table->MIB); + + INDENTED_PRINTF("SSB Mask:\n"); + depth++; + for (int i = 0; i < 2; i++) { + INDENTED_TLV_PRINT("SSB Mask", ssb_table->ssb_mask_list[i].ssb_mask); + } + depth--; + INDENTED_PRINTF("Beam ID:\n"); + depth++; + for (int i = 0; i < 64; i++) { + INDENTED_TLV_PRINT("Beam ID", ssb_table->ssb_beam_id_list[i].beam_id); + } + depth--; + INDENTED_TLV_PRINT("ssPBCH Multiple Carriers in a Band", ssb_table->ss_pbch_multiple_carriers_in_a_band); + INDENTED_TLV_PRINT("Multiple Cells ssPBCH in a Carrier", ssb_table->multiple_cells_ss_pbch_in_a_carrier); + /* TDD Table */ + const nfapi_nr_tdd_table_t *tdd_table = &msg->tdd_table; + if (cell_config->frame_duplex_type.value == 1 /* TDD */) { + INDENTED_TLV_PRINT("TDD Period", tdd_table->tdd_period); + const uint8_t slotsperframe[5] = {10, 20, 40, 80, 160}; + // Assuming always CP_Normal, because Cyclic prefix is not included in CONFIG.request 10.02, but is present in 10.04 + uint8_t cyclicprefix = 1; + // 3GPP 38.211 Table 4.3.2.1 & Table 4.3.2.2 + uint8_t number_of_symbols_per_slot = cyclicprefix ? 14 : 12; + INDENTED_PRINTF("Slot Config:\n"); + depth++; + for (int i = 0; i < slotsperframe[ssb_config->scs_common.value]; i++) { + for (int k = 0; k < number_of_symbols_per_slot; k++) { + const uint8_t slot_type = tdd_table->max_tdd_periodicity_list[i].max_num_of_symbol_per_slot_list[k].slot_config.value; + const char *slot_dir = slot_type == 0 ? "DL" : slot_type == 1 ? "UL" : "S"; + INDENTED_GENERIC_PRINT("(0x%04x) Slot Config", + "%d (%s)", + tdd_table->max_tdd_periodicity_list[i].max_num_of_symbol_per_slot_list[k].slot_config.tl.tag, + slot_type, + slot_dir); + } + } + depth--; + } + /* Measurement Config */ + const nfapi_nr_measurement_config_t *measurement_config = &msg->measurement_config; + INDENTED_TLV_PRINT("RSSI Measurement", measurement_config->rssi_measurement); + /* Beamforming Table */ + const nfapi_nr_dbt_pdu_t *dbt_config = &msg->dbt_config; + INDENTED_PRINTF("Digital Beam Table\n"); + depth++; + INDENTED_GENERIC_PRINT("Num Digital Beams", "%d", dbt_config->num_dig_beams); + INDENTED_GENERIC_PRINT("Num TX RUs", "%d", dbt_config->num_txrus); + depth++; + for (int i = 0; i < dbt_config->num_dig_beams; i++) { + const nfapi_nr_dig_beam_t *dig_beam = &dbt_config->dig_beam_list[i]; + INDENTED_GENERIC_PRINT("Beam IDX", "%d", dig_beam->beam_idx); + depth++; + for (int k = 0; k < dbt_config->num_txrus; k++) { + const nfapi_nr_txru_t *tx_ru = &dig_beam->txru_list[k]; + INDENTED_GENERIC_PRINT("Dig Beam Weight Real", "0x%02x", tx_ru->dig_beam_weight_Re); + INDENTED_GENERIC_PRINT("Dig Beam Weight Imaginary", "0x%02x", tx_ru->dig_beam_weight_Im); + } + depth--; + } + depth--; + depth--; + + /* Precoding Table */ + const nfapi_nr_pm_list_t *pmi_list = &msg->pmi_list; + INDENTED_PRINTF("Precoding Matrix Table\n"); + depth++; + INDENTED_GENERIC_PRINT("Num Precoding Tables", "%d", pmi_list->num_pm_idx); + depth++; + for (int i = 0; i < pmi_list->num_pm_idx; i++) { + const nfapi_nr_pm_pdu_t *pm_pdu = &pmi_list->pmi_pdu[i]; + + INDENTED_GENERIC_PRINT("Precoding Matrix IDX", "0x%02x", pm_pdu->pm_idx); + INDENTED_GENERIC_PRINT("Number of Layers", "%d", pm_pdu->numLayers); + INDENTED_GENERIC_PRINT("Number of Antenna Ports", "%d", pm_pdu->num_ant_ports); + depth++; + for (int k = 0; k < pm_pdu->numLayers; k++) { + for (int l = 0; l < pm_pdu->num_ant_ports; l++) { + const nfapi_nr_pm_weights_t *pm_weights = &pm_pdu->weights[k][l]; + INDENTED_GENERIC_PRINT("Dig Beam Weight Real", "0x%02x", pm_weights->precoder_weight_Re); + INDENTED_GENERIC_PRINT("Dig Beam Weight Imaginary", "0x%02x", pm_weights->precoder_weight_Im); + } + } + depth--; + } + depth--; + depth--; + /* nFAPI Config */ + const nfapi_nr_nfapi_t *nfapi_config = &msg->nfapi_config; + if (nfapi_config->p7_vnf_address_ipv4.tl.tag) { + char ip_str[INET_ADDRSTRLEN]; + INDENTED_GENERIC_PRINT("(0x%04x) P7 VNF Address IPv4", + "%s", + nfapi_config->p7_vnf_address_ipv4.tl.tag, + inet_ntop(AF_INET, nfapi_config->p7_vnf_address_ipv4.address, ip_str, sizeof(ip_str))); + } + if (nfapi_config->p7_vnf_address_ipv6.tl.tag) { + char addr6[INET6_ADDRSTRLEN]; + INDENTED_GENERIC_PRINT("(0x%04x) P7 VNF Address IPv6", + "%s", + nfapi_config->p7_vnf_address_ipv6.tl.tag, + inet_ntop(AF_INET6, nfapi_config->p7_vnf_address_ipv6.address, addr6, sizeof(addr6))); + } + INDENTED_TLV_FORMAT_PRINT("P7 VNF Port", "%d", nfapi_config->p7_vnf_port); + + if (nfapi_config->p7_pnf_address_ipv4.tl.tag) { + char ip_str[INET_ADDRSTRLEN]; + INDENTED_GENERIC_PRINT("(0x%04x) P7 PNF Address IPv4", + "%s", + nfapi_config->p7_pnf_address_ipv4.tl.tag, + inet_ntop(AF_INET, nfapi_config->p7_pnf_address_ipv4.address, ip_str, sizeof(ip_str))); + } + if (nfapi_config->p7_pnf_address_ipv6.tl.tag) { + char addr6[INET6_ADDRSTRLEN]; + INDENTED_GENERIC_PRINT("(0x%04x) P7 PNF Address IPv6", + "%s", + nfapi_config->p7_pnf_address_ipv6.tl.tag, + inet_ntop(AF_INET6, nfapi_config->p7_pnf_address_ipv6.address, addr6, sizeof(addr6))); + } + INDENTED_TLV_FORMAT_PRINT("P7 PNF Port", "%d", nfapi_config->p7_pnf_port); + INDENTED_TLV_FORMAT_PRINT("Timing Window", "%d", nfapi_config->timing_window); + INDENTED_TLV_FORMAT_PRINT("Timing Info Mode", "%d", nfapi_config->timing_info_mode); + INDENTED_TLV_FORMAT_PRINT("Timing Info Period", "%d", nfapi_config->timing_info_period); + INDENTED_TLV_FORMAT_PRINT("DL_TTI Timing Offset", "%d", nfapi_config->dl_tti_timing_offset); + INDENTED_TLV_FORMAT_PRINT("UL_TTI Timing Offset", "%d", nfapi_config->ul_tti_timing_offset); + INDENTED_TLV_FORMAT_PRINT("UL_DCI Timing Offset", "%d", nfapi_config->ul_dci_timing_offset); + INDENTED_TLV_FORMAT_PRINT("TX_DATA Timing Offset", "%d", nfapi_config->tx_data_timing_offset); + /* Beamforming VE */ + const nfapi_nr_analog_beamforming_ve_t *analog_beamforming_ve = &msg->analog_beamforming_ve; + INDENTED_TLV_FORMAT_PRINT("Num Beams per Period", "%d", analog_beamforming_ve->num_beams_period_vendor_ext); + INDENTED_TLV_PRINT("Analog Beamforming VE", analog_beamforming_ve->analog_bf_vendor_ext); + /* Vendor Extension */ + if (msg->vendor_extension) { + const nfapi_tl_t *vendor_extension = (nfapi_tl_t *)&msg->vendor_extension; + switch (vendor_extension->tag) { + case VENDOR_EXT_TLV_1_TAG: { + vendor_ext_tlv_1 *ve = (vendor_ext_tlv_1 *)vendor_extension; + INDENTED_PRINTF("(0x%04x) Vendor extension = %d 0x%02x\n", ve->tl.tag, ve->tl.length, ve->dummy); + } break; + case VENDOR_EXT_TLV_2_TAG: { + vendor_ext_tlv_2 *ve = (vendor_ext_tlv_2 *)vendor_extension; + INDENTED_PRINTF("(0x%04x) Vendor extension = %d 0x%02x\n", ve->tl.tag, ve->tl.length, ve->dummy); + } break; + default: + break; + } + } + depth--; } diff --git a/nfapi/tests/p5/nr_fapi_config_request_test.c b/nfapi/tests/p5/nr_fapi_config_request_test.c index 93ff5b5f3a..384cf13c2b 100644 --- a/nfapi/tests/p5/nr_fapi_config_request_test.c +++ b/nfapi/tests/p5/nr_fapi_config_request_test.c @@ -221,6 +221,21 @@ static void fill_config_request_tlv_tdd_rand(nfapi_nr_config_request_scf_t *nfap FILL_TLV(nfapi_resp->nfapi_config.p7_vnf_port, NFAPI_NR_NFAPI_P7_VNF_PORT_TAG, rand16()); nfapi_resp->num_tlv++; + nfapi_resp->nfapi_config.p7_pnf_address_ipv4.tl.tag = NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV4_TAG; + for (int i = 0; i < NFAPI_IPV4_ADDRESS_LENGTH; ++i) { + nfapi_resp->nfapi_config.p7_pnf_address_ipv4.address[i] = rand8(); + } + nfapi_resp->num_tlv++; + + nfapi_resp->nfapi_config.p7_pnf_address_ipv6.tl.tag = NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV6_TAG; + for (int i = 0; i < NFAPI_IPV6_ADDRESS_LENGTH; ++i) { + nfapi_resp->nfapi_config.p7_pnf_address_ipv6.address[i] = rand8(); + } + nfapi_resp->num_tlv++; + + FILL_TLV(nfapi_resp->nfapi_config.p7_pnf_port, NFAPI_NR_NFAPI_P7_PNF_PORT_TAG, rand16()); + nfapi_resp->num_tlv++; + FILL_TLV(nfapi_resp->nfapi_config.timing_window, NFAPI_NR_NFAPI_TIMING_WINDOW_TAG, rand8()); nfapi_resp->num_tlv++; From 8519c748d1b5454212d81068153b3bc1b4b1231a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BAben=20Soares=20Silva?= Date: Fri, 11 Apr 2025 16:54:47 +0100 Subject: [PATCH 22/35] Add pack/unpack for CONFIG.request Beamforming Table Adds the packing and unpacking functions needed for the DBT Table in CONFIG.request This table tag is specified in SCF222.5.0 (0x1043) and this tag is used to transport the table, previous versions did not include a tag for the table. A struct nfapi_nr_dbt_tlv_ve_t is added to represent this TLV in order to be able to use the pack_nr_tlv function. The necessary additions to the utility functions are done to account for this table. The unitary test is changed to fill this table with randomized data to test transport and copy. --- nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c | 60 ++++++++++++++++++- nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c | 44 ++++++++++++-- .../nfapi/public_inc/nfapi_nr_interface.h | 1 + .../nfapi/public_inc/nfapi_nr_interface_scf.h | 6 ++ nfapi/tests/p5/nr_fapi_config_request_test.c | 19 ++++++ 5 files changed, 124 insertions(+), 6 deletions(-) diff --git a/nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c b/nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c index 281043b6d3..e66ce48ac0 100644 --- a/nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c +++ b/nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c @@ -724,6 +724,28 @@ uint8_t unpack_nr_param_response(uint8_t **ppReadPackedMsg, uint8_t *end, void * &pNfapiMsg->vendor_extension)); } +static uint8_t pack_dbt_table_tlv_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_dbt_tlv_ve_t *dbt_ve = (nfapi_nr_dbt_tlv_ve_t *)tlv; + nfapi_nr_dbt_pdu_t *dbt_config = &dbt_ve->value; + if (!( push16(dbt_config->num_dig_beams, ppWritePackedMsg, end) && push16(dbt_config->num_txrus, ppWritePackedMsg, end) )) { + return 0; + } + for (int i = 0; i< dbt_config->num_dig_beams; i++) { + const nfapi_nr_dig_beam_t *dig_beam = &dbt_config->dig_beam_list[i]; + if (!(push16(dig_beam->beam_idx, ppWritePackedMsg, end))) { + return 0; + } + for (int k = 0; k< dbt_config->num_txrus; k++) { + const nfapi_nr_txru_t *tx_ru = &dig_beam->txru_list[k]; + if (!(push16(tx_ru->dig_beam_weight_Re, ppWritePackedMsg, end) && push16(tx_ru->dig_beam_weight_Im, ppWritePackedMsg, end))) { + return 0; + } + } + } + return 1; +} + uint8_t pack_nr_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { uint8_t *pNumTLVFields = (uint8_t *)*ppWritePackedMsg; @@ -1044,7 +1066,11 @@ uint8_t pack_nr_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *e // END Measurement Config // START Digital Beam Table (DBT) PDU - // Struct in nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h nfapi_nr_dbt_pdu_t, currently unused + if (pNfapiMsg->dbt_config.num_dig_beams != 0) { + nfapi_nr_dbt_tlv_ve_t dbt_tlv = {.tl.tag = NFAPI_NR_CONFIG_BEAMFORMING_TABLE_TAG, .value = pNfapiMsg->dbt_config}; + pack_nr_tlv(NFAPI_NR_CONFIG_BEAMFORMING_TABLE_TAG, &dbt_tlv, ppWritePackedMsg, end, &pack_dbt_table_tlv_value); + numTLVs++; + } // END Digital Beam Table (DBT) PDU // START Precoding Matrix (PM) PDU @@ -1156,6 +1182,33 @@ uint8_t pack_nr_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *e return retval; } +static uint8_t unpack_dbt_table_tlv_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_nr_dbt_pdu_t *dbt_config = (nfapi_nr_dbt_pdu_t *)tlv; + if (!(pull16(ppReadPackedMsg, &dbt_config->num_dig_beams, end) && pull16(ppReadPackedMsg, &dbt_config->num_txrus, end))) { + return 0; + } + if (dbt_config->num_dig_beams > 0) { + dbt_config->dig_beam_list = calloc(dbt_config->num_dig_beams, sizeof(*dbt_config->dig_beam_list)); + } + for (int i = 0; i < dbt_config->num_dig_beams; i++) { + nfapi_nr_dig_beam_t *dig_beam = &dbt_config->dig_beam_list[i]; + if (!(pull16(ppReadPackedMsg, &dig_beam->beam_idx, end))) { + return 0; + } + if (dbt_config->num_txrus > 0) { + dig_beam->txru_list = calloc(dbt_config->num_txrus, sizeof(*dig_beam->txru_list)); + } + for (int k = 0; k < dbt_config->num_txrus; k++) { + nfapi_nr_txru_t *tx_ru = &dig_beam->txru_list[k]; + if (!(pull16(ppReadPackedMsg, &tx_ru->dig_beam_weight_Re, end) && pull16(ppReadPackedMsg, &tx_ru->dig_beam_weight_Im, end))) { + return 0; + } + } + } + return 1; +} + uint8_t unpack_nr_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { // Helper vars for indexed TLVs @@ -1221,6 +1274,7 @@ uint8_t unpack_nr_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void * {NFAPI_NR_FAPI_TOTAL_NUM_BEAMS_VENDOR_EXTENSION_TAG, &(pNfapiMsg->analog_beamforming_ve.total_num_beams_vendor_ext), &unpack_uint8_tlv_value}, {NFAPI_NR_FAPI_ANALOG_BEAM_VENDOR_EXTENSION_TAG, NULL, &unpack_uint8_tlv_value}, {NFAPI_NR_CONFIG_RSSI_MEASUREMENT_TAG, &(pNfapiMsg->measurement_config.rssi_measurement), &unpack_uint8_tlv_value}, + {NFAPI_NR_CONFIG_BEAMFORMING_TABLE_TAG, NULL, &unpack_dbt_table_tlv_value}, {NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV4_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv4), &unpack_ipv4_address_value}, {NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV6_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv6), &unpack_ipv6_address_value}, {NFAPI_NR_NFAPI_P7_VNF_PORT_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_port), &unpack_uint16_tlv_value}, @@ -1268,6 +1322,10 @@ uint8_t unpack_nr_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void * result = (*unpack_fns[idx].unpack_func)(&pNfapiMsg->analog_beamforming_ve.analog_beam_list[beam_ve_idx], ppReadPackedMsg, end); beam_ve_idx ++; break; + case NFAPI_NR_CONFIG_BEAMFORMING_TABLE_TAG: + unpack_fns[idx].tlv = &generic_tl; + result = (*unpack_fns[idx].unpack_func)(&pNfapiMsg->dbt_config, ppReadPackedMsg, end); + break; case NFAPI_NR_CONFIG_NUM_PRACH_FD_OCCASIONS_TAG: pNfapiMsg->prach_config.num_prach_fd_occasions.tl.tag = generic_tl.tag; pNfapiMsg->prach_config.num_prach_fd_occasions.tl.length = generic_tl.length; diff --git a/nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c b/nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c index 52f2ee8031..4df5169d8c 100644 --- a/nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c +++ b/nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c @@ -259,6 +259,22 @@ bool eq_config_request(const nfapi_nr_config_request_scf_t *unpacked_req, const EQ_TLV(unpacked_req->measurement_config.rssi_measurement, req->measurement_config.rssi_measurement); + EQ(unpacked_req->dbt_config.num_dig_beams, req->dbt_config.num_dig_beams); + + EQ(unpacked_req->dbt_config.num_txrus, req->dbt_config.num_txrus); + + for (int i = 0; i < req->dbt_config.num_dig_beams; i++) { + const nfapi_nr_dig_beam_t *unpacked_dig_beam = &unpacked_req->dbt_config.dig_beam_list[i]; + const nfapi_nr_dig_beam_t *req_dig_beam = &req->dbt_config.dig_beam_list[i]; + EQ(unpacked_dig_beam->beam_idx, req_dig_beam->beam_idx); + for (int k = 0; k < req->dbt_config.num_txrus; ++k) { + const nfapi_nr_txru_t *unpacked_tx_ru = &unpacked_dig_beam->txru_list[k]; + const nfapi_nr_txru_t *req_tx_ru = &req_dig_beam->txru_list[k]; + EQ(unpacked_tx_ru->dig_beam_weight_Re, req_tx_ru->dig_beam_weight_Re); + EQ(unpacked_tx_ru->dig_beam_weight_Im, req_tx_ru->dig_beam_weight_Im); + } + } + EQ(unpacked_req->nfapi_config.p7_vnf_address_ipv4.tl.tag, req->nfapi_config.p7_vnf_address_ipv4.tl.tag); for (int i = 0; i < NFAPI_IPV4_ADDRESS_LENGTH; ++i) { EQ(unpacked_req->nfapi_config.p7_vnf_address_ipv4.address[i], req->nfapi_config.p7_vnf_address_ipv4.address[i]); @@ -406,9 +422,7 @@ void free_param_response(nfapi_nr_param_response_scf_t *msg) void free_config_request(nfapi_nr_config_request_scf_t *msg) { - if (msg->vendor_extension) { - free(msg->vendor_extension); - } + free(msg->vendor_extension); if (msg->prach_config.num_prach_fd_occasions_list) { for (int i = 0; i < msg->prach_config.num_prach_fd_occasions.value; i++) { @@ -427,10 +441,14 @@ void free_config_request(nfapi_nr_config_request_scf_t *msg) free(msg->tdd_table.max_tdd_periodicity_list); } - if (msg->pmi_list.pmi_pdu) { - free(msg->pmi_list.pmi_pdu); + for (int i = 0; i < msg->dbt_config.num_dig_beams; i++) { + free(msg->dbt_config.dig_beam_list[i].txru_list); } + free(msg->dbt_config.dig_beam_list); + + free(msg->pmi_list.pmi_pdu); + if (msg->analog_beamforming_ve.analog_beam_list) { free(msg->analog_beamforming_ve.analog_beam_list); } @@ -807,6 +825,22 @@ void copy_config_request(const nfapi_nr_config_request_scf_t *src, nfapi_nr_conf COPY_TLV(dst->measurement_config.rssi_measurement, src->measurement_config.rssi_measurement); + dst->dbt_config.num_dig_beams = src->dbt_config.num_dig_beams; + dst->dbt_config.num_txrus = src->dbt_config.num_txrus; + dst->dbt_config.dig_beam_list = calloc(dst->dbt_config.num_dig_beams, sizeof(*dst->dbt_config.dig_beam_list)); + for (int i = 0; i < dst->dbt_config.num_dig_beams; i++) { + nfapi_nr_dig_beam_t *dst_dig_beam = &dst->dbt_config.dig_beam_list[i]; + const nfapi_nr_dig_beam_t *src_dig_beam = &src->dbt_config.dig_beam_list[i]; + dst_dig_beam->beam_idx = src_dig_beam->beam_idx; + dst_dig_beam->txru_list = calloc(dst->dbt_config.num_txrus , sizeof(*dst_dig_beam->txru_list )); + for (int k = 0; k < dst->dbt_config.num_txrus; ++k) { + nfapi_nr_txru_t *dst_tx_ru = &dst_dig_beam->txru_list[k]; + const nfapi_nr_txru_t *src_tx_ru = &src_dig_beam->txru_list[k]; + dst_tx_ru->dig_beam_weight_Re = src_tx_ru->dig_beam_weight_Re; + dst_tx_ru->dig_beam_weight_Im = src_tx_ru->dig_beam_weight_Im; + } + } + COPY_TL(dst->nfapi_config.p7_vnf_address_ipv4.tl, src->nfapi_config.p7_vnf_address_ipv4.tl); memcpy(dst->nfapi_config.p7_vnf_address_ipv4.address, src->nfapi_config.p7_vnf_address_ipv4.address, diff --git a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h index b7e6577fa2..eb668f3e73 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h @@ -34,6 +34,7 @@ #define NFAPI_NR_FAPI_TOTAL_NUM_BEAMS_VENDOR_EXTENSION_TAG 0xA002 #define NFAPI_NR_FAPI_ANALOG_BEAM_VENDOR_EXTENSION_TAG 0xA003 + typedef struct { uint16_t phy_id; uint16_t message_id; diff --git a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h index 0533a76c6d..7af9d07d1c 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h @@ -328,6 +328,7 @@ typedef struct #define NFAPI_NR_CONFIG_RSSI_MEASUREMENT_TAG 0x1028 #define NFAPI_NR_CONFIG_TDD_TABLE 0x1035 +#define NFAPI_NR_CONFIG_BEAMFORMING_TABLE_TAG 0x1043 // This tag was added in version 5 of the SCF222 standard ( Table 3-50 of SCF222.10.05 ) //table 3-21 typedef struct @@ -473,6 +474,11 @@ typedef struct { nfapi_nr_dig_beam_t *dig_beam_list; } nfapi_nr_dbt_pdu_t; +typedef struct { + nfapi_tl_t tl; + nfapi_nr_dbt_pdu_t value; +} nfapi_nr_dbt_tlv_ve_t; + // Table 3–62 Precoding matrix (PM) PDU (v.222.10.04) typedef struct { int16_t precoder_weight_Re; diff --git a/nfapi/tests/p5/nr_fapi_config_request_test.c b/nfapi/tests/p5/nr_fapi_config_request_test.c index 384cf13c2b..7964af55c0 100644 --- a/nfapi/tests/p5/nr_fapi_config_request_test.c +++ b/nfapi/tests/p5/nr_fapi_config_request_test.c @@ -206,6 +206,25 @@ static void fill_config_request_tlv_tdd_rand(nfapi_nr_config_request_scf_t *nfap FILL_TLV(nfapi_resp->measurement_config.rssi_measurement, NFAPI_NR_CONFIG_RSSI_MEASUREMENT_TAG, rand8()); nfapi_resp->num_tlv++; + uint16_t nb_beams = rand16_range(1, 15); + uint16_t nb_tx = rand16_range(1, 15); + nfapi_resp->dbt_config.num_dig_beams = nb_beams; + if (nfapi_resp->dbt_config.num_dig_beams > 0) { + nfapi_resp->dbt_config.num_txrus = nb_tx; + nfapi_resp->dbt_config.dig_beam_list = calloc(nb_beams , sizeof(*nfapi_resp->dbt_config.dig_beam_list)); + for (int i = 0; i < nb_beams; i++) { + nfapi_nr_dig_beam_t *beam = &nfapi_resp->dbt_config.dig_beam_list[i]; + beam->beam_idx = i; + beam->txru_list = calloc(nb_tx , sizeof(*beam->txru_list)); + for (int j = 0; j < nb_tx; j++) { + nfapi_nr_txru_t *txru = &beam->txru_list[j]; + txru->dig_beam_weight_Re = rand16_range(1, 0xffff); + txru->dig_beam_weight_Im = rand16_range(1, 0xffff); + } + } + nfapi_resp->num_tlv++; + } + nfapi_resp->nfapi_config.p7_vnf_address_ipv4.tl.tag = NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV4_TAG; for (int i = 0; i < NFAPI_IPV4_ADDRESS_LENGTH; ++i) { nfapi_resp->nfapi_config.p7_vnf_address_ipv4.address[i] = rand8(); From 018d456a2a8807de4302538a29516fd23ee87d83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BAben=20Soares=20Silva?= Date: Thu, 22 May 2025 10:09:46 +0100 Subject: [PATCH 23/35] Add pack/unpack for CONFIG.request Precoding Matrix table Adds the packing and unpacking functions needed for the PM Table in CONFIG.request This table tag is specified in SCF222.10.06(0x104B), previous versions didn't have a tag for this table, and this version of the spec introduces the parameter `num_pm_idx`, previously not present. A struct nfapi_nr_pm_tlv_ve_t is added to represent this TLV in order to be able to use the pack_nr_tlv function. The necessary additions to the utility functions are done to account for this table. The unitary test is changed to fill this table with randomized data to test transport and copy. --- nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c | 65 ++++++++++++++++++- nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c | 38 +++++++++++ .../nfapi/public_inc/nfapi_nr_interface_scf.h | 8 ++- nfapi/tests/p5/nr_fapi_config_request_test.c | 22 +++++++ 4 files changed, 131 insertions(+), 2 deletions(-) diff --git a/nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c b/nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c index e66ce48ac0..6bf2ff37ea 100644 --- a/nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c +++ b/nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c @@ -746,6 +746,31 @@ static uint8_t pack_dbt_table_tlv_value(void *tlv, uint8_t **ppWritePackedMsg, u return 1; } +static uint8_t pack_pm_table_tlv_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_pm_tlv_ve_t *pm_ve = (nfapi_nr_pm_tlv_ve_t *)tlv; + nfapi_nr_pm_list_t *pmi_list = &pm_ve->value; + if (!( push16(pmi_list->num_pm_idx, ppWritePackedMsg, end) )) { + return 0; + } + for (int i = 0; i< pmi_list->num_pm_idx; i++) { + const nfapi_nr_pm_pdu_t *pm_pdu = &pmi_list->pmi_pdu[i]; + if (!(push16(pm_pdu->pm_idx, ppWritePackedMsg, end) && push16(pm_pdu->numLayers, ppWritePackedMsg, end) + && push16(pm_pdu->num_ant_ports, ppWritePackedMsg, end))) { + return 0; + } + for (int k = 0; k < pm_pdu->numLayers; k++) { + for (int j = 0; j < pm_pdu->num_ant_ports; j++) { + const nfapi_nr_pm_weights_t *pm_weight = &pm_pdu->weights[k][j]; + if (!(push16(pm_weight->precoder_weight_Re, ppWritePackedMsg, end) && push16(pm_weight->precoder_weight_Im, ppWritePackedMsg, end))) { + return 0; + } + } + } + } + return 1; +} + uint8_t pack_nr_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { uint8_t *pNumTLVFields = (uint8_t *)*ppWritePackedMsg; @@ -1074,7 +1099,11 @@ uint8_t pack_nr_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *e // END Digital Beam Table (DBT) PDU // START Precoding Matrix (PM) PDU - // Struct in nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h nfapi_nr_pm_pdu_t, currently unused, tag to use for AERIAL + if (pNfapiMsg->pmi_list.num_pm_idx != 0) { + nfapi_nr_pm_tlv_ve_t pm_tlv = {.tl.tag = NFAPI_NR_CONFIG_PRECODING_TABLE_V6_TAG, .value = pNfapiMsg->pmi_list}; + pack_nr_tlv(NFAPI_NR_CONFIG_PRECODING_TABLE_V6_TAG, &pm_tlv, ppWritePackedMsg, end, &pack_pm_table_tlv_value); + numTLVs++; + } // is 0xA011 END Precoding Matrix (PM) PDU #ifndef ENABLE_AERIAL // START nFAPI TLVs included in CONFIG.request for IDLE and CONFIGURED states @@ -1209,6 +1238,35 @@ static uint8_t unpack_dbt_table_tlv_value(void *tlv, uint8_t **ppReadPackedMsg, return 1; } +static uint8_t unpack_pm_table_tlv_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_nr_pm_list_t *pm_list = (nfapi_nr_pm_list_t *)tlv; + if (!(pull16(ppReadPackedMsg, &pm_list->num_pm_idx, end))) { + return 0; + } + if (pm_list->num_pm_idx > 0) { + pm_list->pmi_pdu = calloc(pm_list->num_pm_idx, sizeof(*pm_list->pmi_pdu)); + } + for (int i = 0; i < pm_list->num_pm_idx; i++) { + nfapi_nr_pm_pdu_t *pm_pdu = &pm_list->pmi_pdu[i]; + if (!(pull16(ppReadPackedMsg, &pm_pdu->pm_idx, end) && pull16(ppReadPackedMsg, &pm_pdu->numLayers, end) + && pull16(ppReadPackedMsg, &pm_pdu->num_ant_ports, end))) { + return 0; + } + AssertFatal(pm_pdu->numLayers <= 4 && pm_pdu->num_ant_ports <= 4, "Precoding matrix size limited to 4X4 for the time being\n"); + for (int k = 0; k < pm_pdu->numLayers; k++) { + for (int j = 0; j < pm_pdu->num_ant_ports; j++) { + nfapi_nr_pm_weights_t *pm_weight = &pm_pdu->weights[k][j]; + if (!(pulls16(ppReadPackedMsg, &pm_weight->precoder_weight_Re, end) + && pulls16(ppReadPackedMsg, &pm_weight->precoder_weight_Im, end))) { + return 0; + } + } + } + } + return 1; +} + uint8_t unpack_nr_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { // Helper vars for indexed TLVs @@ -1275,6 +1333,7 @@ uint8_t unpack_nr_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void * {NFAPI_NR_FAPI_ANALOG_BEAM_VENDOR_EXTENSION_TAG, NULL, &unpack_uint8_tlv_value}, {NFAPI_NR_CONFIG_RSSI_MEASUREMENT_TAG, &(pNfapiMsg->measurement_config.rssi_measurement), &unpack_uint8_tlv_value}, {NFAPI_NR_CONFIG_BEAMFORMING_TABLE_TAG, NULL, &unpack_dbt_table_tlv_value}, + {NFAPI_NR_CONFIG_PRECODING_TABLE_V6_TAG, NULL, &unpack_pm_table_tlv_value}, {NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV4_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv4), &unpack_ipv4_address_value}, {NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV6_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv6), &unpack_ipv6_address_value}, {NFAPI_NR_NFAPI_P7_VNF_PORT_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_port), &unpack_uint16_tlv_value}, @@ -1326,6 +1385,10 @@ uint8_t unpack_nr_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void * unpack_fns[idx].tlv = &generic_tl; result = (*unpack_fns[idx].unpack_func)(&pNfapiMsg->dbt_config, ppReadPackedMsg, end); break; + case NFAPI_NR_CONFIG_PRECODING_TABLE_V6_TAG: + unpack_fns[idx].tlv = &generic_tl; + result = (*unpack_fns[idx].unpack_func)(&pNfapiMsg->pmi_list, ppReadPackedMsg, end); + break; case NFAPI_NR_CONFIG_NUM_PRACH_FD_OCCASIONS_TAG: pNfapiMsg->prach_config.num_prach_fd_occasions.tl.tag = generic_tl.tag; pNfapiMsg->prach_config.num_prach_fd_occasions.tl.length = generic_tl.length; diff --git a/nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c b/nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c index 4df5169d8c..fc34c66df9 100644 --- a/nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c +++ b/nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c @@ -275,6 +275,24 @@ bool eq_config_request(const nfapi_nr_config_request_scf_t *unpacked_req, const } } + EQ(unpacked_req->pmi_list.num_pm_idx, req->pmi_list.num_pm_idx); + + for (int i = 0; i < req->pmi_list.num_pm_idx; i++) { + const nfapi_nr_pm_pdu_t *req_pmi_pdu = &req->pmi_list.pmi_pdu[i]; + const nfapi_nr_pm_pdu_t *unpacked_pmi_pdu = &unpacked_req->pmi_list.pmi_pdu[i]; + EQ(unpacked_pmi_pdu->pm_idx, req_pmi_pdu->pm_idx); + EQ(unpacked_pmi_pdu->numLayers, req_pmi_pdu->numLayers); + EQ(unpacked_pmi_pdu->num_ant_ports, req_pmi_pdu->num_ant_ports); + for (int j = 0; j < req_pmi_pdu->num_ant_ports; ++j) { + for (int k = 0; k < req_pmi_pdu->num_ant_ports; ++k) { + const nfapi_nr_pm_weights_t* req_pm_weight = &req_pmi_pdu->weights[j][k]; + const nfapi_nr_pm_weights_t* unpacked_pm_weight = &unpacked_pmi_pdu->weights[j][k]; + EQ(unpacked_pm_weight->precoder_weight_Re, req_pm_weight->precoder_weight_Re); + EQ(unpacked_pm_weight->precoder_weight_Im, req_pm_weight->precoder_weight_Im); + } + } + } + EQ(unpacked_req->nfapi_config.p7_vnf_address_ipv4.tl.tag, req->nfapi_config.p7_vnf_address_ipv4.tl.tag); for (int i = 0; i < NFAPI_IPV4_ADDRESS_LENGTH; ++i) { EQ(unpacked_req->nfapi_config.p7_vnf_address_ipv4.address[i], req->nfapi_config.p7_vnf_address_ipv4.address[i]); @@ -841,6 +859,26 @@ void copy_config_request(const nfapi_nr_config_request_scf_t *src, nfapi_nr_conf } } + dst->pmi_list.num_pm_idx = src->pmi_list.num_pm_idx; + if (dst->pmi_list.num_pm_idx > 0) { + dst->pmi_list.pmi_pdu = calloc(dst->pmi_list.num_pm_idx , sizeof(*dst->pmi_list.pmi_pdu)); + for (int i = 0; i < dst->pmi_list.num_pm_idx; i++) { + nfapi_nr_pm_pdu_t * dst_pmi_pdu = &dst->pmi_list.pmi_pdu[i]; + const nfapi_nr_pm_pdu_t * src_pmi_pdu = &src->pmi_list.pmi_pdu[i]; + dst_pmi_pdu->pm_idx = src_pmi_pdu->pm_idx; + dst_pmi_pdu->numLayers = src_pmi_pdu->numLayers; + dst_pmi_pdu->num_ant_ports = src_pmi_pdu->num_ant_ports; + for (int j = 0; j < dst_pmi_pdu->numLayers; ++j) { + for (int k = 0; k < dst_pmi_pdu->num_ant_ports; ++k) { + nfapi_nr_pm_weights_t* dst_pm_weight = &dst_pmi_pdu->weights[j][k]; + const nfapi_nr_pm_weights_t* src_pm_weight = &src_pmi_pdu->weights[j][k]; + dst_pm_weight->precoder_weight_Re = src_pm_weight->precoder_weight_Re; + dst_pm_weight->precoder_weight_Im = src_pm_weight->precoder_weight_Im; + } + } + } + } + COPY_TL(dst->nfapi_config.p7_vnf_address_ipv4.tl, src->nfapi_config.p7_vnf_address_ipv4.tl); memcpy(dst->nfapi_config.p7_vnf_address_ipv4.address, src->nfapi_config.p7_vnf_address_ipv4.address, diff --git a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h index 7af9d07d1c..f213868328 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h @@ -329,6 +329,7 @@ typedef struct #define NFAPI_NR_CONFIG_RSSI_MEASUREMENT_TAG 0x1028 #define NFAPI_NR_CONFIG_TDD_TABLE 0x1035 #define NFAPI_NR_CONFIG_BEAMFORMING_TABLE_TAG 0x1043 // This tag was added in version 5 of the SCF222 standard ( Table 3-50 of SCF222.10.05 ) +#define NFAPI_NR_CONFIG_PRECODING_TABLE_V6_TAG 0x104B // This tag was added in version 6 of the SCF222 standard ( Table 3-52 of SCF222.10.06 ) //table 3-21 typedef struct @@ -497,7 +498,12 @@ typedef struct { typedef struct { uint16_t num_pm_idx; nfapi_nr_pm_pdu_t *pmi_pdu; -} nfapi_nr_pm_list_t; +} nfapi_nr_pm_list_t; // This corresponds to Table 3-69 of SCF222.10.06, which introduces the num_pm_idx parameter + +typedef struct { + nfapi_tl_t tl; + nfapi_nr_pm_list_t value; +} nfapi_nr_pm_tlv_ve_t; typedef struct { nfapi_uint8_tlv_t num_beams_period_vendor_ext; diff --git a/nfapi/tests/p5/nr_fapi_config_request_test.c b/nfapi/tests/p5/nr_fapi_config_request_test.c index 7964af55c0..82ce60ca3b 100644 --- a/nfapi/tests/p5/nr_fapi_config_request_test.c +++ b/nfapi/tests/p5/nr_fapi_config_request_test.c @@ -225,6 +225,28 @@ static void fill_config_request_tlv_tdd_rand(nfapi_nr_config_request_scf_t *nfap nfapi_resp->num_tlv++; } + nfapi_nr_pm_list_t *pm_list = &nfapi_resp->pmi_list; + const uint16_t num_layers = rand16_range(1, 4); + const uint16_t num_ant_ports = rand16_range(1, 4); + pm_list->num_pm_idx = rand16_range(1, 4); + if (nfapi_resp->pmi_list.num_pm_idx > 0) { + pm_list->pmi_pdu = calloc(pm_list->num_pm_idx, sizeof(*pm_list->pmi_pdu)); + for (int i = 0; i < pm_list->num_pm_idx; i++) { + nfapi_nr_pm_pdu_t *pmi_pdu = &pm_list->pmi_pdu[i]; + pmi_pdu->pm_idx = i+1; + pmi_pdu->numLayers = num_layers; + pmi_pdu->num_ant_ports = num_ant_ports; + for (int j = 0; j < num_layers; j++) { + for (int k = 0; k < num_ant_ports; k++) { + nfapi_nr_pm_weights_t* pm_weight = &pmi_pdu->weights[j][k]; + pm_weight->precoder_weight_Re = (int16_t)rand16_range(1, 0xffff); + pm_weight->precoder_weight_Im = (int16_t)rand16_range(1, 0xffff); + } + } + } + nfapi_resp->num_tlv++; + } + nfapi_resp->nfapi_config.p7_vnf_address_ipv4.tl.tag = NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV4_TAG; for (int i = 0; i < NFAPI_IPV4_ADDRESS_LENGTH; ++i) { nfapi_resp->nfapi_config.p7_vnf_address_ipv4.address[i] = rand8(); From d3205ea09a451e98e52307905fab689072932220 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BAben=20Soares=20Silva?= Date: Thu, 22 May 2025 10:31:26 +0100 Subject: [PATCH 24/35] Finish dump procedure for CONFIG.response message Remove unnecessary checks on free_config_response --- nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c | 65 +++++++++++++++----- 1 file changed, 50 insertions(+), 15 deletions(-) diff --git a/nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c b/nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c index fc34c66df9..6b238dd69d 100644 --- a/nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c +++ b/nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c @@ -474,25 +474,15 @@ void free_config_request(nfapi_nr_config_request_scf_t *msg) void free_config_response(nfapi_nr_config_response_scf_t *msg) { - if (msg->vendor_extension) { - free(msg->vendor_extension); - } + free(msg->vendor_extension); - if (msg->invalid_tlvs_list) { - free(msg->invalid_tlvs_list); - } + free(msg->invalid_tlvs_list); - if (msg->invalid_tlvs_configured_in_idle_list) { - free(msg->invalid_tlvs_configured_in_idle_list); - } + free(msg->invalid_tlvs_configured_in_idle_list); - if (msg->invalid_tlvs_configured_in_running_list) { - free(msg->invalid_tlvs_configured_in_running_list); - } + free(msg->invalid_tlvs_configured_in_running_list); - if (msg->missing_tlvs_list) { - free(msg->missing_tlvs_list); - } + free(msg->missing_tlvs_list); } void free_start_request(nfapi_nr_start_request_scf_t *msg) @@ -1407,6 +1397,32 @@ void dump_config_request(const nfapi_nr_config_request_scf_t *msg) depth--; } +static void dump_generic_tlv(const nfapi_nr_generic_tlv_scf_t* tlv, int depth) +{ + INDENTED_PRINTF("TLV tag 0x%02x , Length 0x%02x , Value ", tlv->tl.tag, tlv->tl.length); + switch (tlv->tl.length) { + case UINT_8: + printf("0x%x\n", tlv->value.u8); + break; + case UINT_16: + printf("0x%02x\n", tlv->value.u16); + break; + case UINT_32: + printf("0x%04x\n", tlv->value.u32); + break; + case ARRAY_UINT_16: + for (int i = 0; i< 5 ; i++) { + printf("0x%04x ", tlv->value.array_u16[i]); + } + printf("\n"); + break; + default: + printf("unknown length %d\n", tlv->tl.length); + DevAssert(1 == 0); + break; + } +} + void dump_config_response(const nfapi_nr_config_response_scf_t *msg) { int depth = 0; @@ -1419,6 +1435,25 @@ void dump_config_response(const nfapi_nr_config_response_scf_t *msg) msg->num_invalid_tlvs_configured_in_running); INDENTED_PRINTF("Number of Missing TLVs = 0x%02x\n", msg->num_missing_tlvs); /* dump all TLVs from each table */ + INDENTED_PRINTF("Invalid or Unsupported TLVs (%d) :\n",msg->num_invalid_tlvs); + for (int i = 0; i < msg->num_invalid_tlvs; ++i) { + dump_generic_tlv(&msg->invalid_tlvs_list[i], depth+1); + } + + INDENTED_PRINTF("TLVs that can only be configured in IDLE (%d):\n", msg->num_invalid_tlvs_configured_in_idle); + for (int i = 0; i < msg->num_invalid_tlvs; ++i) { + dump_generic_tlv(&msg->invalid_tlvs_list[i], depth+1); + } + + INDENTED_PRINTF("TLVs that can only be configured in RUNNING (%d):\n",msg->num_invalid_tlvs_configured_in_running); + for (int i = 0; i < msg->num_invalid_tlvs; ++i) { + dump_generic_tlv(&msg->invalid_tlvs_list[i], depth+1); + } + + INDENTED_PRINTF("Missing TLVs (%d):\n",msg->num_missing_tlvs); + for (int i = 0; i < msg->num_invalid_tlvs; ++i) { + dump_generic_tlv(&msg->invalid_tlvs_list[i], depth+1); + } depth--; } From c9835a13e7b5fec65f8e5a0f2495eb804367ec1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BAben=20Soares=20Silva?= Date: Thu, 22 May 2025 10:36:31 +0100 Subject: [PATCH 25/35] Finish dump procedure for TX_DATA.request message --- nfapi/open-nFAPI/fapi/src/nr_fapi_p7_utils.c | 28 ++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/nfapi/open-nFAPI/fapi/src/nr_fapi_p7_utils.c b/nfapi/open-nFAPI/fapi/src/nr_fapi_p7_utils.c index 9939a6f535..14846d6f5b 100644 --- a/nfapi/open-nFAPI/fapi/src/nr_fapi_p7_utils.c +++ b/nfapi/open-nFAPI/fapi/src/nr_fapi_p7_utils.c @@ -2586,6 +2586,27 @@ void dump_ul_dci_request(const nfapi_nr_ul_dci_request_t *msg) } } +static void dump_tx_data_request_tlv(const nfapi_nr_tx_data_request_tlv_t *tlv, int depth) +{ + INDENTED_PRINTF("Tag = %d\n", tlv->tag); + INDENTED_PRINTF("Length = %d\n", tlv->length); + INDENTED_PRINTF("Value = "); + switch (tlv->tag) { + case 0: + for (int i = 0; i < tlv->length; i++) { + printf("0x%02x ", ((uint8_t*)tlv->value.direct)[i]); + } + break; + case 1: + printf("%p", tlv->value.ptr); + break; + default: + printf( " Unknown tag value %d",tlv->tag); + break; + } + printf("\n"); +} + void dump_tx_data_request(const nfapi_nr_tx_data_request_t *msg) { int depth = 0; @@ -2594,15 +2615,18 @@ void dump_tx_data_request(const nfapi_nr_tx_data_request_t *msg) INDENTED_PRINTF("SFN = %d\n", msg->SFN); INDENTED_PRINTF("Slot = %d\n", msg->Slot); INDENTED_PRINTF("Number of PDUs = %d\n", msg->Number_of_PDUs); + depth++; for (int i = 0; i < msg->Number_of_PDUs; i++) { - depth++; INDENTED_PRINTF("PDU #%d\n", i); const nfapi_nr_pdu_t *pdu = &msg->pdu_list[i]; INDENTED_PRINTF("PDU Length = 0x%02x\n", pdu->PDU_length); INDENTED_PRINTF("PDU Index = 0x%02x\n", pdu->PDU_index); INDENTED_PRINTF("numTLV = 0x%02x\n", pdu->num_TLV); + for (int tlv_idx = 0; tlv_idx < pdu->num_TLV; tlv_idx++) { + const nfapi_nr_tx_data_request_tlv_t *tlv = &pdu->TLVs[tlv_idx]; /* call to dump_tx_data_request_tlv */ - depth--; + dump_tx_data_request_tlv(tlv, depth + 1); + } } } From 923cfc9cd2e7a7960639f3bb0da31eabc78b2837 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BAben=20Soares=20Silva?= Date: Thu, 22 May 2025 11:14:21 +0100 Subject: [PATCH 26/35] Finish dump procedure for UCI.indication message Remove unnecessary checks on free_uci_indication --- nfapi/open-nFAPI/fapi/src/nr_fapi_p7_utils.c | 246 ++++++++++++++----- 1 file changed, 186 insertions(+), 60 deletions(-) diff --git a/nfapi/open-nFAPI/fapi/src/nr_fapi_p7_utils.c b/nfapi/open-nFAPI/fapi/src/nr_fapi_p7_utils.c index 14846d6f5b..bf99375203 100644 --- a/nfapi/open-nFAPI/fapi/src/nr_fapi_p7_utils.c +++ b/nfapi/open-nFAPI/fapi/src/nr_fapi_p7_utils.c @@ -930,72 +930,56 @@ void free_crc_indication(nfapi_nr_crc_indication_t *msg) void free_uci_indication(nfapi_nr_uci_indication_t *msg) { - if (msg->uci_list) { - for (int pdu_idx = 0; pdu_idx < msg->num_ucis; ++pdu_idx) { - nfapi_nr_uci_t *uci_pdu = &msg->uci_list[pdu_idx]; - switch (uci_pdu->pdu_type) { - case NFAPI_NR_UCI_PUSCH_PDU_TYPE: { - nfapi_nr_uci_pusch_pdu_t *pdu = &uci_pdu->pusch_pdu; - // Bit 0 not used in PUSCH PDU - // HARQ - if ((pdu->pduBitmap >> 1) & 0x01) { - if (pdu->harq.harq_payload) { - free(pdu->harq.harq_payload); - } - } - // CSI Part 1 - if ((pdu->pduBitmap >> 2) & 0x01) { - if (pdu->csi_part1.csi_part1_payload) { - free(pdu->csi_part1.csi_part1_payload); - } - } - // CSI Part 2 - if ((pdu->pduBitmap >> 3) & 0x01) { - if (pdu->csi_part2.csi_part2_payload) { - free(pdu->csi_part2.csi_part2_payload); - } - } - break; + for (int pdu_idx = 0; pdu_idx < msg->num_ucis; ++pdu_idx) { + nfapi_nr_uci_t *uci_pdu = &msg->uci_list[pdu_idx]; + switch (uci_pdu->pdu_type) { + case NFAPI_NR_UCI_PUSCH_PDU_TYPE: { + nfapi_nr_uci_pusch_pdu_t *pdu = &uci_pdu->pusch_pdu; + // Bit 0 not used in PUSCH PDU + // HARQ + if ((pdu->pduBitmap >> 1) & 0x01) { + free(pdu->harq.harq_payload); } - case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: { - // Nothing to free - break; + // CSI Part 1 + if ((pdu->pduBitmap >> 2) & 0x01) { + free(pdu->csi_part1.csi_part1_payload); } - case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: { - nfapi_nr_uci_pucch_pdu_format_2_3_4_t *pdu = &uci_pdu->pucch_pdu_format_2_3_4; - // SR - if (pdu->pduBitmap & 0x01) { - if (pdu->sr.sr_payload) { - free(pdu->sr.sr_payload); - } - } - // HARQ - if ((pdu->pduBitmap >> 1) & 0x01) { - if (pdu->harq.harq_payload) { - free(pdu->harq.harq_payload); - } - } - // CSI Part 1 - if ((pdu->pduBitmap >> 2) & 0x01) { - if (pdu->csi_part1.csi_part1_payload) { - free(pdu->csi_part1.csi_part1_payload); - } - } - // CSI Part 2 - if ((pdu->pduBitmap >> 3) & 0x01) { - if (pdu->csi_part2.csi_part2_payload) { - free(pdu->csi_part2.csi_part2_payload); - } - } - break; + // CSI Part 2 + if ((pdu->pduBitmap >> 3) & 0x01) { + free(pdu->csi_part2.csi_part2_payload); } - default: - AssertFatal(1 == 0, "Unknown UCI.indication PDU Type %d\n", uci_pdu->pdu_type); - break; + break; } + case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: { + // Nothing to free + break; + } + case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: { + nfapi_nr_uci_pucch_pdu_format_2_3_4_t *pdu = &uci_pdu->pucch_pdu_format_2_3_4; + // SR + if (pdu->pduBitmap & 0x01) { + free(pdu->sr.sr_payload); + } + // HARQ + if ((pdu->pduBitmap >> 1) & 0x01) { + free(pdu->harq.harq_payload); + } + // CSI Part 1 + if ((pdu->pduBitmap >> 2) & 0x01) { + free(pdu->csi_part1.csi_part1_payload); + } + // CSI Part 2 + if ((pdu->pduBitmap >> 3) & 0x01) { + free(pdu->csi_part2.csi_part2_payload); + } + break; + } + default: + AssertFatal(1 == 0, "Unknown UCI.indication PDU Type %d\n", uci_pdu->pdu_type); + break; } - free(msg->uci_list); } + free(msg->uci_list); } void free_srs_indication(nfapi_nr_srs_indication_t *msg) @@ -2688,6 +2672,134 @@ void dump_crc_indication(const nfapi_nr_crc_indication_t *msg) } } +static void dump_harq_2_3_4(const nfapi_nr_harq_pdu_2_3_4_t *harq, int depth) +{ + INDENTED_PRINTF("HARQ CRC = %01x\n", harq->harq_crc); + INDENTED_PRINTF("HARQ Bit Length = %d\n", harq->harq_bit_len); + INDENTED_PRINTF("HARQ Payload = "); + for (int i = 0; i < harq->harq_bit_len / 8 + 1; i++) { + printf("%x ", harq->harq_payload[i]); + } + printf("\n"); +} + +static void dump_csi_part_1(const nfapi_nr_csi_part1_pdu_t *csi, int depth) +{ + INDENTED_PRINTF("CSI Part 1 CRC = %01x\n", csi->csi_part1_crc); + INDENTED_PRINTF("CSI Part 1 Bit Length = %d\n", csi->csi_part1_bit_len); + INDENTED_PRINTF("CSI Part 1 Payload = "); + for (int i = 0; i < csi->csi_part1_bit_len / 8 + 1; i++) { + printf("%x ", csi->csi_part1_payload[i]); + } + printf("\n"); +} + +static void dump_csi_part_2(const nfapi_nr_csi_part2_pdu_t *csi, int depth) +{ + INDENTED_PRINTF("CSI Part 1 CRC = %01x\n", csi->csi_part2_crc); + INDENTED_PRINTF("CSI Part 1 Bit Length = %d\n", csi->csi_part2_bit_len); + INDENTED_PRINTF("CSI Part 1 Payload = "); + for (int i = 0; i < csi->csi_part2_bit_len / 8 + 1; i++) { + printf("%x ", csi->csi_part2_payload[i]); + } + printf("\n"); +} + +static void dump_uci_PUSCH_PDU(const nfapi_nr_uci_pusch_pdu_t *pdu, int depth) +{ + INDENTED_PRINTF("PDU Bitmap = 0x%01x\n", pdu->pduBitmap); + INDENTED_PRINTF("Handle = 0x%04x\n", pdu->handle); + INDENTED_PRINTF("RNTI = 0x%02x\n", pdu->rnti); + INDENTED_PRINTF("UL_CQI = 0x%02x\n", pdu->ul_cqi); + INDENTED_PRINTF("Timing Advance = 0x%02x\n", pdu->timing_advance); + INDENTED_PRINTF("RSSI = 0x%02x\n", pdu->rssi); + // HARQ payload, CSI Part 1 and 2 are conditionally allocated + if ((pdu->pduBitmap >> 1) & 0x01) { + INDENTED_PRINTF("HARQ Information\n"); + dump_harq_2_3_4(&pdu->harq, depth + 1); + } + if ((pdu->pduBitmap >> 2) & 0x01) { + INDENTED_PRINTF("CSI Part 1\n"); + dump_csi_part_1(&pdu->csi_part1, depth + 1); + } + if ((pdu->pduBitmap >> 3) & 0x01) { + INDENTED_PRINTF("CSI Part 1\n"); + dump_csi_part_2(&pdu->csi_part2, depth + 1); + } +} + +static void dump_sr_0_1(const nfapi_nr_sr_pdu_0_1_t *sr, int depth) +{ + INDENTED_PRINTF("SR Indication = 0x%02x\n", sr->sr_indication); + INDENTED_PRINTF("SR Confidence Level = 0x%02x\n", sr->sr_confidence_level); +} + +static void dump_harq_0_1(const nfapi_nr_harq_pdu_0_1_t *harq, int depth) +{ + INDENTED_PRINTF("Num HARQ = 0x%02x\n", harq->num_harq); + INDENTED_PRINTF("HARQ Confidence Level = 0x%02x\n", harq->harq_confidence_level); + depth++; + for (int i = 0; i < harq->num_harq; i++) { + INDENTED_PRINTF("HARQ Value[%d] : 0x%02x \n", i, harq->harq_list[i].harq_value); + } +} + +static void dump_uci_PUCCH_0_1(const nfapi_nr_uci_pucch_pdu_format_0_1_t *pdu, int depth) +{ + INDENTED_PRINTF("PDU Bitmap = 0x%01x\n", pdu->pduBitmap); + INDENTED_PRINTF("Handle = 0x%04x\n", pdu->handle); + INDENTED_PRINTF("RNTI = 0x%02x\n", pdu->rnti); + INDENTED_PRINTF("PUCCH Format = 0x%02x\n", pdu->pucch_format); + INDENTED_PRINTF("UL_CQI = 0x%02x\n", pdu->ul_cqi); + INDENTED_PRINTF("Timing Advance = 0x%02x\n", pdu->timing_advance); + INDENTED_PRINTF("RSSI = 0x%02x\n", pdu->rssi); + if ((pdu->pduBitmap) & 0x01) { + INDENTED_PRINTF("SR Information\n"); + dump_sr_0_1(&pdu->sr, depth + 1); + } + if ((pdu->pduBitmap >> 1) & 0x01) { + INDENTED_PRINTF("HARQ Information\n"); + dump_harq_0_1(&pdu->harq, depth + 1); + } +} + +static void dump_sr_2_3_4(const nfapi_nr_sr_pdu_2_3_4_t *sr, int depth) +{ + INDENTED_PRINTF("SR Bit Length = %d\n", sr->sr_bit_len); + INDENTED_PRINTF("SR Payload "); + for (int i = 0; i < sr->sr_bit_len / 8 + 1; i++) { + printf("%x ", sr->sr_payload[i]); + } + printf("\n"); +} + +static void dump_uci_PUCCH_2_3_4(const nfapi_nr_uci_pucch_pdu_format_2_3_4_t *pdu, int depth) +{ + INDENTED_PRINTF("PDU Bitmap = 0x%01x\n", pdu->pduBitmap); + INDENTED_PRINTF("Handle = 0x%04x\n", pdu->handle); + INDENTED_PRINTF("RNTI = 0x%02x\n", pdu->rnti); + INDENTED_PRINTF("PUCCH Format = 0x%02x\n", pdu->pucch_format); + INDENTED_PRINTF("UL_CQI = 0x%02x\n", pdu->ul_cqi); + INDENTED_PRINTF("Timing Advance = 0x%02x\n", pdu->timing_advance); + INDENTED_PRINTF("RSSI = 0x%02x\n", pdu->rssi); + // SR + if (pdu->pduBitmap & 0x01) { + dump_sr_2_3_4(&pdu->sr, depth + 1); + } + // HARQ + if ((pdu->pduBitmap >> 1) & 0x01) { + dump_harq_2_3_4(&pdu->harq, depth + 1); + } + // CSI Part 1 + if ((pdu->pduBitmap >> 2) & 0x01) { + dump_csi_part_1(&pdu->csi_part1, depth + 1); + } + // CSI Part 2 + if ((pdu->pduBitmap >> 3) & 0x01) { + dump_csi_part_2(&pdu->csi_part2, depth + 1); + } +} + void dump_uci_indication(const nfapi_nr_uci_indication_t *msg) { int depth = 0; @@ -2704,6 +2816,20 @@ void dump_uci_indication(const nfapi_nr_uci_indication_t *msg) INDENTED_PRINTF("PDUType = 0x%02x\n", uci->pdu_type); INDENTED_PRINTF("PDUSize = 0x%02x\n", uci->pdu_size); /* call to dump_uci_indication__pdu */ + switch (uci->pdu_type) { + case NFAPI_NR_UCI_PUSCH_PDU_TYPE: + dump_uci_PUSCH_PDU(&uci->pusch_pdu, depth + 1); + break; + case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: + dump_uci_PUCCH_0_1(&uci->pucch_pdu_format_0_1, depth + 1); + break; + case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: + dump_uci_PUCCH_2_3_4(&uci->pucch_pdu_format_2_3_4, depth + 1); + break; + default: + INDENTED_PRINTF("Unknown PDU type 0x%02x\n", uci->pdu_type); + break; + } depth--; } } From 625fd54ae25e14e733f8069a1cb9cbfec3a886a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BAben=20Soares=20Silva?= Date: Thu, 12 Jun 2025 13:14:08 +0100 Subject: [PATCH 27/35] Remove unnecessary checks on P5 free utility functions --- nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c | 24 +++++--------------- 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c b/nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c index 6b238dd69d..4c3f32ef27 100644 --- a/nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c +++ b/nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c @@ -425,9 +425,7 @@ bool eq_error_indication(const nfapi_nr_error_indication_scf_t *unpacked_req, co void free_param_request(nfapi_nr_param_request_scf_t *msg) { - if (msg->vendor_extension) { - free(msg->vendor_extension); - } + free(msg->vendor_extension); } void free_param_response(nfapi_nr_param_response_scf_t *msg) @@ -487,37 +485,27 @@ void free_config_response(nfapi_nr_config_response_scf_t *msg) void free_start_request(nfapi_nr_start_request_scf_t *msg) { - if (msg->vendor_extension) { - free(msg->vendor_extension); - } + free(msg->vendor_extension); } void free_start_response(nfapi_nr_start_response_scf_t *msg) { - if (msg->vendor_extension) { - free(msg->vendor_extension); - } + free(msg->vendor_extension); } void free_stop_request(nfapi_nr_stop_request_scf_t *msg) { - if (msg->vendor_extension) { - free(msg->vendor_extension); - } + free(msg->vendor_extension); } void free_stop_indication(nfapi_nr_stop_indication_scf_t *msg) { - if (msg->vendor_extension) { - free(msg->vendor_extension); - } + free(msg->vendor_extension); } void free_error_indication(nfapi_nr_error_indication_scf_t *msg) { - if (msg->vendor_extension) { - free(msg->vendor_extension); - } + free(msg->vendor_extension); } void copy_param_request(const nfapi_nr_param_request_scf_t *src, nfapi_nr_param_request_scf_t *dst) From ba4608d46b79a3fdc02553d37288de15d5b41baf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BAben=20Soares=20Silva?= Date: Thu, 12 Jun 2025 13:15:47 +0100 Subject: [PATCH 28/35] Remove unnecessary checks on P7 free utility functions --- nfapi/open-nFAPI/fapi/src/nr_fapi_p7_utils.c | 28 ++++++-------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/nfapi/open-nFAPI/fapi/src/nr_fapi_p7_utils.c b/nfapi/open-nFAPI/fapi/src/nr_fapi_p7_utils.c index bf99375203..fb645707ad 100644 --- a/nfapi/open-nFAPI/fapi/src/nr_fapi_p7_utils.c +++ b/nfapi/open-nFAPI/fapi/src/nr_fapi_p7_utils.c @@ -859,9 +859,7 @@ bool eq_rach_indication(const nfapi_nr_rach_indication_t *a, const nfapi_nr_rach void free_dl_tti_request(nfapi_nr_dl_tti_request_t *msg) { - if (msg->vendor_extension) { - free(msg->vendor_extension); - } + free(msg->vendor_extension); } void free_ul_tti_request(nfapi_nr_ul_tti_request_t *msg) @@ -907,9 +905,7 @@ void free_rx_data_indication(nfapi_nr_rx_data_indication_t *msg) if (msg->number_of_pdus > 0) { for (int pdu_idx = 0; pdu_idx < msg->number_of_pdus; ++pdu_idx) { nfapi_nr_rx_data_pdu_t *rx_pdu = &msg->pdu_list[pdu_idx]; - if (rx_pdu->pdu) { - free(rx_pdu->pdu); - } + free(rx_pdu->pdu); } free(msg->pdu_list); } @@ -917,15 +913,11 @@ void free_rx_data_indication(nfapi_nr_rx_data_indication_t *msg) void free_crc_indication(nfapi_nr_crc_indication_t *msg) { - if (msg->crc_list) { - for (int crc_idx = 0; crc_idx < msg->number_crcs; ++crc_idx) { - nfapi_nr_crc_t *crc = &msg->crc_list[crc_idx]; - if (crc->cb_crc_status) { - free(crc->cb_crc_status); - } - } - free(msg->crc_list); + for (int crc_idx = 0; crc_idx < msg->number_crcs; ++crc_idx) { + nfapi_nr_crc_t *crc = &msg->crc_list[crc_idx]; + free(crc->cb_crc_status); } + free(msg->crc_list); } void free_uci_indication(nfapi_nr_uci_indication_t *msg) @@ -984,16 +976,12 @@ void free_uci_indication(nfapi_nr_uci_indication_t *msg) void free_srs_indication(nfapi_nr_srs_indication_t *msg) { - if (msg->pdu_list) { - free(msg->pdu_list); - } + free(msg->pdu_list); } void free_rach_indication(nfapi_nr_rach_indication_t *msg) { - if (msg->pdu_list) { - free(msg->pdu_list); - } + free(msg->pdu_list); } static void copy_dl_tti_beamforming(const nfapi_nr_tx_precoding_and_beamforming_t *src, From aca48aa9f80cc7ade932318652faa265fce26eb6 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 17 Jun 2025 09:41:02 +0200 Subject: [PATCH 29/35] gNB RRC: handle optional measResultQuantity fields independently Closes: #970 --- openair2/RRC/NR/rrc_gNB.c | 52 ++++++++++++++++++++++++--------------- 1 file changed, 32 insertions(+), 20 deletions(-) diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index f69e03b810..2ef11ce605 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -2542,6 +2542,34 @@ void rrc_gNB_process_e1_bearer_context_release_cplt(const e1ap_bearer_release_cp LOG_I(RRC, "UE %d: received bearer release complete\n", cplt->gNB_cu_cp_ue_id); } +static void print_meas_result_quantity(FILE *f, const NR_MeasQuantityResults_t *mqr) +{ + fprintf(f, " resultSSB:"); + if (!mqr) { + fprintf(f, " NOT PROVIDED\n"); + return; + } + if (mqr->rsrp) { + const long rrsrp = *mqr->rsrp - 156; + fprintf(f, " RSRP %ld dBm", rrsrp); + } else { + fprintf(f, " RSRP not provided"); + } + if (mqr->rsrq) { + const float rrsrq = (float) (*mqr->rsrq - 87) / 2.0f; + fprintf(f, " RSRQ %.1f dB", rrsrq); + } else { + fprintf(f, " RSRQ not provided"); + } + if (mqr->sinr) { + const float rsinr = (float) (*mqr->sinr - 46) / 2.0f; + fprintf(f, " SINR %.1f dB", rsinr); + } else { + fprintf(f, " SINR not provided"); + } + fprintf(f, "\n"); +} + static void print_rrc_meas(FILE *f, const NR_MeasResults_t *measresults) { DevAssert(measresults->measResultServingMOList.list.count >= 1); @@ -2550,37 +2578,21 @@ static void print_rrc_meas(FILE *f, const NR_MeasResults_t *measresults) NR_MeasResultServMO_t *measresultservmo = measresults->measResultServingMOList.list.array[0]; NR_MeasResultNR_t *measresultnr = &measresultservmo->measResultServingCell; - NR_MeasQuantityResults_t *mqr = measresultnr->measResult.cellResults.resultsSSB_Cell; if (measresultnr->physCellId) fprintf(f, - " servingCellId %ld MeasResultNR for phyCellId %ld:\n resultSSB:", + " servingCellId %ld MeasResultNR for phyCellId %ld:\n", measresultservmo->servCellId, *measresultnr->physCellId); - if (mqr != NULL) { - const long rrsrp = *mqr->rsrp - 156; - const float rrsrq = (float) (*mqr->rsrq - 87) / 2.0f; - const float rsinr = (float) (*mqr->sinr - 46) / 2.0f; - fprintf(f, "RSRP %ld dBm RSRQ %.1f dB SINR %.1f dB\n", rrsrp, rrsrq, rsinr); - } else { - fprintf(f, "NOT PROVIDED\n"); - } + print_meas_result_quantity(f, measresultnr->measResult.cellResults.resultsSSB_Cell); if (measresults->measResultNeighCells && measresults->measResultNeighCells->present == NR_MeasResults__measResultNeighCells_PR_measResultListNR) { NR_MeasResultListNR_t *meas_neigh = measresults->measResultNeighCells->choice.measResultListNR; for (int i = 0; i < meas_neigh->list.count; ++i) { NR_MeasResultNR_t *measresultneigh = meas_neigh->list.array[i]; - NR_MeasQuantityResults_t *neigh_mqr = measresultneigh->measResult.cellResults.resultsSSB_Cell; if (measresultneigh->physCellId) - fprintf(f, " neighboring cell for phyCellId %ld:\n resultSSB:", *measresultneigh->physCellId); - if (mqr != NULL) { - const long rrsrp = *neigh_mqr->rsrp - 156; - const float rrsrq = (float)(*neigh_mqr->rsrq - 87) / 2.0f; - const float rsinr = (float)(*neigh_mqr->sinr - 46) / 2.0f; - fprintf(f, "RSRP %ld dBm RSRQ %.1f dB SINR %.1f dB\n", rrsrp, rrsrq, rsinr); - } else { - fprintf(f, "NOT PROVIDED\n"); - } + fprintf(f, " neighboring cell for phyCellId %ld:\n", *measresultneigh->physCellId); + print_meas_result_quantity(f, measresultneigh->measResult.cellResults.resultsSSB_Cell); } } } From 6fc02164c586dff80c4af6957998f2f131b02b98 Mon Sep 17 00:00:00 2001 From: Raghavendra Dinavahi Date: Tue, 8 Apr 2025 16:54:13 +0200 Subject: [PATCH 30/35] UE changes: Handling of ulsyncvalidityduration IE in sib19 Spec 38.331 section 5.2.2.4.21 indicates this 1> start or restart T430 for serving cell with the timer value set to ntn-UlSyncValidityDuration for the serving cell from the subframe indicated by epochTime for the serving cell; NOTE: UE should attempt to re-acquire SIB19 before the end of the duration indicated by ntn-UlSyncValidityDuration and epochTime Epochtime IE When explicitly provided through SIB, or through dedicated signaling, the EpochTime is the starting time of a DL sub-frame, indicated by a SFN and a sub-frame number signaled together with the assistance information. For serving cell, the field sfn indicates the current SFN or the next upcoming SFN after the frame where the message indicating the epochTime is received. This field is mandatory present when ntn-Config is provided in dedicated configuration. gNB implementation related to epochtime will be done in a separate merge request. --- openair2/LAYER2/NR_MAC_UE/mac_proto.h | 7 +- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 8 +- openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c | 13 +- openair2/RRC/NR_UE/rrc_UE.c | 206 ++++++++++++++++-- openair2/RRC/NR_UE/rrc_defs.h | 9 + openair2/RRC/NR_UE/rrc_proto.h | 2 +- openair2/RRC/NR_UE/rrc_timers_and_constants.c | 8 + 7 files changed, 220 insertions(+), 33 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index b058f6e681..f5e36bd7d5 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -67,13 +67,16 @@ void release_common_ss_cset(NR_BWP_PDCCH_t *pdcch); \param gNB_index gNB index \param sibs_mask sibs mask \param pduP pointer to pdu - \param pdu_length length of pdu */ + \param pdu_length length of pdu + \param frame,slot Received TTI*/ void nr_ue_decode_BCCH_DL_SCH(NR_UE_MAC_INST_t *mac, int cc_id, unsigned int gNB_index, uint8_t ack_nack, uint8_t *pduP, - uint32_t pdu_len); + uint32_t pdu_len, + int frame, + int slot); void release_dl_BWP(NR_UE_MAC_INST_t *mac, int index); void release_ul_BWP(NR_UE_MAC_INST_t *mac, int index); diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 16aa7dcb8f..7cedc11e75 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -305,11 +305,13 @@ void nr_ue_decode_BCCH_DL_SCH(NR_UE_MAC_INST_t *mac, unsigned int gNB_index, uint8_t ack_nack, uint8_t *pduP, - uint32_t pdu_len) + uint32_t pdu_len, + int frame, + int slot) { if(ack_nack) { LOG_D(NR_MAC, "Decoding NR-BCCH-DL-SCH-Message (SIB1 or SI)\n"); - nr_mac_rrc_data_ind_ue(mac->ue_id, cc_id, gNB_index, 0, 0, 0, mac->physCellId, 0, NR_BCCH_DL_SCH, (uint8_t *) pduP, pdu_len); + nr_mac_rrc_data_ind_ue(mac->ue_id, cc_id, gNB_index, frame, slot, 0, mac->physCellId, 0, NR_BCCH_DL_SCH, (uint8_t *) pduP, pdu_len); if (mac->get_sib1) mac->get_sib1 = false; for (int i = 0; i < MAX_SI_GROUPS; i++) { @@ -325,7 +327,7 @@ void nr_ue_decode_BCCH_DL_SCH(NR_UE_MAC_INST_t *mac, } else { LOG_E(NR_MAC, "Got NACK on NR-BCCH-DL-SCH-Message (%s)\n", mac->get_sib1 ? "SIB1" : "other SI"); - nr_mac_rrc_data_ind_ue(mac->ue_id, cc_id, gNB_index, 0, 0, 0, mac->physCellId, 0, NR_BCCH_DL_SCH, NULL, 0); + nr_mac_rrc_data_ind_ue(mac->ue_id, cc_id, gNB_index, frame, slot, 0, mac->physCellId, 0, NR_BCCH_DL_SCH, NULL, 0); } } diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c index 0d0829181e..7c8c2a6b21 100644 --- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c @@ -1106,9 +1106,11 @@ static int handle_bcch_dlsch(NR_UE_MAC_INST_t *mac, unsigned int gNB_index, uint8_t ack_nack, uint8_t *pduP, - uint32_t pdu_len) + uint32_t pdu_len, + int frame, + int slot) { - nr_ue_decode_BCCH_DL_SCH(mac, cc_id, gNB_index, ack_nack, pduP, pdu_len); + nr_ue_decode_BCCH_DL_SCH(mac, cc_id, gNB_index, ack_nack, pduP, pdu_len, frame, slot); return 0; } @@ -1290,10 +1292,13 @@ static uint32_t nr_ue_dl_processing(NR_UE_MAC_INST_t *mac, nr_downlink_indicatio break; case FAPI_NR_RX_PDU_TYPE_SIB: ret_mask |= (handle_bcch_dlsch(mac, - dl_info->cc_id, dl_info->gNB_index, + dl_info->cc_id, + dl_info->gNB_index, rx_indication_body.pdsch_pdu.ack_nack, rx_indication_body.pdsch_pdu.pdu, - rx_indication_body.pdsch_pdu.pdu_length)) << FAPI_NR_RX_PDU_TYPE_SIB; + rx_indication_body.pdsch_pdu.pdu_length, + dl_info->frame, + dl_info->slot)) << FAPI_NR_RX_PDU_TYPE_SIB; break; case FAPI_NR_RX_PDU_TYPE_DLSCH: ret_mask |= (handle_dlsch(mac, dl_info, i)) << FAPI_NR_RX_PDU_TYPE_DLSCH; diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index b36c2d676d..17eaca5e9c 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -144,7 +144,8 @@ static void process_lte_nsa_msg(NR_UE_RRC_INST_t *rrc, nsa_msg_t *msg, int msg_l static void nr_rrc_ue_process_ueCapabilityEnquiry(NR_UE_RRC_INST_t *rrc, NR_UECapabilityEnquiry_t *UECapabilityEnquiry); static void nr_rrc_ue_process_masterCellGroup(NR_UE_RRC_INST_t *rrc, OCTET_STRING_t *masterCellGroup, - long *fullConfig); + long *fullConfig, + int gNB_index); static void nr_rrc_ue_process_measConfig(rrcPerNB_t *rrc, NR_MeasConfig_t *const measConfig, NR_UE_Timers_Constants_t *timers); @@ -165,7 +166,120 @@ static void set_DRB_status(NR_UE_RRC_INST_t *rrc, NR_DRB_Identity_t drb_id, NR_R rrc->status_DRBs[drb_id - 1] = status; } -static void nr_decode_SI(NR_UE_RRC_SI_INFO *SI_info, NR_SystemInformation_t *si, NR_UE_RRC_INST_t *rrc) +static int get_ulsyncvalidityduration_timer_value(NR_NTN_Config_r17_t *ntncfg) +{ + int retval = 0; + AssertFatal(ntncfg, "NTN-Config IE not present\n"); + + if (ntncfg->ntn_UlSyncValidityDuration_r17) { + const int values[] = {5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 120, 180, 240, 900}; + retval = values[*ntncfg->ntn_UlSyncValidityDuration_r17]; + } + + return retval; +} + +static void get_epochtime_from_sib19scheduling(NR_UE_RRC_SI_INFO *SI_info, int *frame, int *subframe) +{ + // TS 38.331 section 5.2.2.3.2 + // SI-window starts at the slot #a, where a = x mod N + // x = (si-WindowPosition -1) × w, where w is the si-WindowLength; + // N is the number of slots in a radio frame + int wl_slots = 5 << SI_info->si_windowlength; + int x = (SI_info->sib19_windowposition - 1) * wl_slots; + int slots_per_subframe = 1 << SI_info->scs; + int N = slots_per_subframe * 10; + int slot_end_sib19_window = (x % N) + wl_slots; + + *frame += (slot_end_sib19_window / N); + int slot = slot_end_sib19_window % N; + *subframe = ceil(slot / slots_per_subframe); + + LOG_D(NR_RRC, + "Get EPOCHTIME: x:%d, N:%d, slot_endw:%d, frame:%d, subframe:%d , slot:%d\n", + x, + N, + slot_end_sib19_window, + *frame, + *subframe, + slot); +} + +static int eval_epoch_time(NR_UE_RRC_SI_INFO *SI_info, NR_NTN_Config_r17_t *ntncfg, int frame) +{ + int epoch_frame = 0, epoch_subframe = 0; + int diff_frames = 0; + AssertFatal(frame >= 0, "Frame Incorrect, results in incorrect EPOCH time evaluation\n"); + if (ntncfg->epochTime_r17) { + epoch_frame = ntncfg->epochTime_r17->sfn_r17; + epoch_subframe = ntncfg->epochTime_r17->subFrameNR_r17; + } else { + // EPOCH time is optional in case of SIB19. This case happens only in case of SIB19 NTN config + // If no EPOCH time is sent, epochtime points to SIB19 window end slot in the current scheduling window + epoch_frame = frame; + epoch_subframe = 0; + get_epochtime_from_sib19scheduling(SI_info, &epoch_frame, &epoch_subframe); + // Adding epochTime IE in SIB19, later MAC will use it. + ntncfg->epochTime_r17 = CALLOC(1, sizeof(NR_EpochTime_r17_t)); + ntncfg->epochTime_r17->sfn_r17 = epoch_frame; + ntncfg->epochTime_r17->subFrameNR_r17 = epoch_subframe; + } + // For serving cell, the field sfn indicates the current SFN or the next upcoming SFN + // after the frame where the message indicating the epochTime is received + // i.e. Epochframe can be present or future SFN + diff_frames = (epoch_frame - frame + 1024) % 1024; // According to 38.331 Epochtime is defined for serving cell like this + LOG_D(NR_RRC, "Epoch frame %d, ahead by %d frames\n", epoch_frame, diff_frames); + return diff_frames; +} + +static int get_ntn_timervalues(NR_UE_RRC_SI_INFO *SI_info, NR_NTN_Config_r17_t *ntncfg, int diff_frames, int *val430_ms) +{ + int val430 = get_ulsyncvalidityduration_timer_value(ntncfg); + int sib19_periodicity_ms = (SI_info->sib19_periodicity + 1) * 10; + *val430_ms = val430 * 1000 + diff_frames * 10; // in ms + if (*val430_ms <= sib19_periodicity_ms) + LOG_E(NR_RRC, "Too small T430 value. Might result in frequent ULSYNC failure\n"); + + // Depending on ulsyncvalidity duration, SIB19 timer expires 15secs/2secs before T430 + // LArger values might be used for GEO and epoch time interval can be around 10 secs + // Lower values will be used for NGSO (LEO/MEO), epoch time interval can be between 2-3 secs. + // TODO remove the hardoded values and define a better strategy to determine the time of expiry + // with real GEO/LEO/MEO SATs. + int expire_before_ms = ((val430 >= 120) ? 10000 : 2000); + int diff = *val430_ms - expire_before_ms; + int sib19_timer_ms = (diff > 0) ? diff : ((*val430_ms - sib19_periodicity_ms) > 0) ? (*val430_ms - sib19_periodicity_ms) : 0; + LOG_D(NR_RRC, "val430:%d s, T430:%d ms, sib19_timer:%d ms\n", val430, *val430_ms, sib19_timer_ms); + return sib19_timer_ms; +} + +static void nr_rrc_process_ntnconfig(NR_UE_RRC_INST_t *rrc, NR_UE_RRC_SI_INFO *SI_info, NR_NTN_Config_r17_t *ntncfg, int frame) +{ + SI_info->SInfo_r17.sib19_validity = true; + // Check if Epochtime is sent or not + int diff_frames = eval_epoch_time(SI_info, ntncfg, frame); + + if (ntncfg->ntn_UlSyncValidityDuration_r17) { // ulsyncvalidity duration configured + int val430_ms = 0, sib19_timer_ms = 0; + sib19_timer_ms = get_ntn_timervalues(SI_info, ntncfg, diff_frames, &val430_ms); + // T430 should be started only in connected mode. + // Inorder to avoid starting T430 when entering connected mode, T430 is started as soon as + // SIB19 is received, and if UE enters connected mode T430 will be in running. + // T430 expiry in RRC idle or inactive states does nothing. + nr_timer_setup(&rrc->timers_and_constants.T430, val430_ms, 10); + nr_timer_start(&rrc->timers_and_constants.T430); + // SIB19 should be received before T430 expires + // SIB19 validity timer should expire before T430 expiry such that new SIB19 is read + if (sib19_timer_ms > 0) { + nr_timer_setup(&SI_info->SInfo_r17.sib19_timer, sib19_timer_ms, 10); + nr_timer_start(&SI_info->SInfo_r17.sib19_timer); + } else + // This makes sure that SIB19 is read again in the next window + SI_info->SInfo_r17.sib19_validity = false; + } else + nr_timer_start(&SI_info->SInfo_r17.sib19_timer); +} + +static void nr_decode_SI(NR_UE_RRC_SI_INFO *SI_info, NR_SystemInformation_t *si, NR_UE_RRC_INST_t *rrc, int frame) { instance_t ue_id = rrc->ue_id; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_UE_DECODE_SI, VCD_FUNCTION_IN); @@ -240,11 +354,10 @@ static void nr_decode_SI(NR_UE_RRC_SI_INFO *SI_info, NR_SystemInformation_t *si, nr_timer_start(&SI_info->sib14_timer); break; case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib19_v1700: - SI_info->SInfo_r17.sib19_validity = true; - if (g_log->log_component[NR_RRC].level >= OAILOG_DEBUG) - xer_fprint(stdout, &asn_DEF_NR_SIB19_r17, (const void *)typeandinfo->choice.sib19_v1700); sib19 = typeandinfo->choice.sib19_v1700; - nr_timer_start(&SI_info->SInfo_r17.sib19_timer); + if (g_log->log_component[NR_RRC].level >= OAILOG_DEBUG) + xer_fprint(stdout, &asn_DEF_NR_SIB19_r17, (const void *)sib19); + nr_rrc_process_ntnconfig(rrc, SI_info, sib19->ntn_Config_r17, frame); break; default: break; @@ -335,6 +448,27 @@ static bool verify_NTN_access(const NR_UE_RRC_SI_INFO *SI_info, const NR_SIB1_v1 return ntn_access && sib19_present; } +static void get_sib19_schedinfo(NR_UE_RRC_SI_INFO *SI_info, NR_SI_SchedulingInfo_v1700_t *si_SchedInfo_v1700) +{ + // Find the SIB19 periodicity configured in the scheduling info + if (si_SchedInfo_v1700) { + int count_v17 = si_SchedInfo_v1700->schedulingInfoList2_r17.list.count; + for (int i = 0; i < count_v17; i++) { + struct NR_SchedulingInfo2_r17 *schedulingInfo2 = si_SchedInfo_v1700->schedulingInfoList2_r17.list.array[i]; + for (int j = 0; j < schedulingInfo2->sib_MappingInfo_r17.list.count; j++) { + struct NR_SIB_TypeInfo_v1700 *sib_TypeInfo_v1700 = schedulingInfo2->sib_MappingInfo_r17.list.array[j]; + if (sib_TypeInfo_v1700->sibType_r17.present == NR_SIB_TypeInfo_v1700__sibType_r17_PR_type1_r17) { + if (sib_TypeInfo_v1700->sibType_r17.choice.type1_r17 == NR_SIB_TypeInfo_v1700__sibType_r17__type1_r17_sibType19) { + SI_info->sib19_periodicity = 8 << schedulingInfo2->si_Periodicity_r17; + SI_info->sib19_windowposition = schedulingInfo2->si_WindowPosition_r17; + return; + } + } + } + } + } +} + static void nr_rrc_process_sib1(NR_UE_RRC_INST_t *rrc, NR_UE_RRC_SI_INFO *SI_info, NR_SIB1_t *sib1) { if(g_log->log_component[NR_RRC].level >= OAILOG_DEBUG) @@ -355,9 +489,14 @@ static void nr_rrc_process_sib1(NR_UE_RRC_INST_t *rrc, NR_UE_RRC_SI_INFO *SI_inf si_SchedInfo_v1700 = sib1_v1700->si_SchedulingInfo_v1700; } + AssertFatal(sib1->servingCellConfigCommon, "configuration issue in SIB1\n"); + SI_info->scs = sib1->servingCellConfigCommon->downlinkConfigCommon.initialDownlinkBWP.genericParameters.subcarrierSpacing; + SI_info->si_windowlength = (sib1->si_SchedulingInfo) ? sib1->si_SchedulingInfo->si_WindowLength : 0; // configure default SI nr_rrc_configure_default_SI(SI_info, sib1->si_SchedulingInfo, si_SchedInfo_v1700); rrc->is_NTN_UE = verify_NTN_access(SI_info, sib1_v1700); + if (rrc->is_NTN_UE) + get_sib19_schedinfo(SI_info, si_SchedInfo_v1700); // configure timers and constant nr_rrc_set_sib1_timers_and_constants(&rrc->timers_and_constants, sib1); @@ -376,7 +515,7 @@ static void nr_rrc_process_reconfiguration_v1530(NR_UE_RRC_INST_t *rrc, NR_RRCRe LOG_E(NR_RRC, "RRCReconfiguration includes fullConfig but this is not implemented yet\n"); } if (rec_1530->masterCellGroup) - nr_rrc_ue_process_masterCellGroup(rrc, rec_1530->masterCellGroup, rec_1530->fullConfig); + nr_rrc_ue_process_masterCellGroup(rrc, rec_1530->masterCellGroup, rec_1530->fullConfig, gNB_index); if (rec_1530->masterKeyUpdate) { // TODO perform AS security key update procedure as specified in 5.3.5.7 LOG_E(NR_RRC, "RRCReconfiguration includes masterKeyUpdate but this is not implemented yet\n"); @@ -426,7 +565,7 @@ static void nr_rrc_process_reconfiguration_v1530(NR_UE_RRC_INST_t *rrc, NR_RRCRe SEQUENCE_free(&asn_DEF_NR_SystemInformation, si, 1); } else { LOG_I(NR_RRC, "[UE %ld] Decoding dedicatedSystemInformationDelivery\n", rrc->ue_id); - nr_decode_SI(SI_info, si, rrc); + nr_decode_SI(SI_info, si, rrc, rrc->current_frame); } } if (rec_1530->otherConfig) { @@ -502,7 +641,7 @@ static void nr_rrc_ue_process_rrcReconfiguration(NR_UE_RRC_INST_t *rrc, int gNB_ if (LOG_DEBUGFLAG(DEBUG_ASN1)) xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void *) cellGroupConfig); - nr_rrc_cellgroup_configuration(rrc, cellGroupConfig); + nr_rrc_cellgroup_configuration(rrc, cellGroupConfig, gNB_index); AssertFatal(!IS_SA_MODE(get_softmodem_params()), "secondaryCellGroup only used in NSA for now\n"); MessageDef *msg = itti_alloc_new_message(TASK_RRC_NRUE, 0, NR_MAC_RRC_CONFIG_CG); @@ -924,7 +1063,9 @@ static void nr_rrc_ue_decode_NR_BCCH_DL_SCH_Message(NR_UE_RRC_INST_t *rrc, uint8_t *const Sdu, const uint8_t Sdu_len, const uint8_t rsrq, - const uint8_t rsrp) + const uint8_t rsrp, + int frame, + int slot) { NR_UE_RRC_SI_INFO *SI_info = &rrc->perNB[gNB_index].SInfo; SI_info->sib_pending = false; @@ -960,9 +1101,9 @@ static void nr_rrc_ue_decode_NR_BCCH_DL_SCH_Message(NR_UE_RRC_INST_t *rrc, bcch_message->message.choice.c1->choice.systemInformationBlockType1 = NULL; break; case NR_BCCH_DL_SCH_MessageType__c1_PR_systemInformation: - LOG_I(NR_RRC, "[UE %ld] Decoding SI\n", rrc->ue_id); + LOG_I(NR_RRC, "[UE %ld] %d:%d Decoding SI\n", rrc->ue_id, frame, slot); NR_SystemInformation_t *si = bcch_message->message.choice.c1->choice.systemInformation; - nr_decode_SI(SI_info, si, rrc); + nr_decode_SI(SI_info, si, rrc, frame); break; case NR_BCCH_DL_SCH_MessageType__c1_PR_NOTHING: default: @@ -1019,7 +1160,9 @@ static void nr_rrc_manage_rlc_bearers(NR_UE_RRC_INST_t *rrc, } } -static void nr_rrc_process_reconfigurationWithSync(NR_UE_RRC_INST_t *rrc, NR_ReconfigurationWithSync_t *reconfigurationWithSync) +static void nr_rrc_process_reconfigurationWithSync(NR_UE_RRC_INST_t *rrc, + NR_ReconfigurationWithSync_t *reconfigurationWithSync, + int gNB_index) { // perform Reconfiguration with sync according to 5.3.5.5.2 if (!rrc->as_security_activated && !(get_softmodem_params()->phy_test || get_softmodem_params()->do_ra)) { @@ -1046,15 +1189,26 @@ static void nr_rrc_process_reconfigurationWithSync(NR_UE_RRC_INST_t *rrc, NR_Rec } rrc->rnti = reconfigurationWithSync->newUE_Identity; // reset the MAC entity of this cell group (done at MAC in handle_reconfiguration_with_sync) + + // 3GPP TS38.331 section 5.3.5.5.2 + nr_timer_stop(&tac->T430); + if (reconfigurationWithSync->spCellConfigCommon && + reconfigurationWithSync->spCellConfigCommon->ext2 && + reconfigurationWithSync->spCellConfigCommon->ext2->ntn_Config_r17) { + NR_NTN_Config_r17_t *ntncfg = reconfigurationWithSync->spCellConfigCommon->ext2->ntn_Config_r17; + // EPOCH time is always sent if NTN config is sent through DCCH + AssertFatal(ntncfg->epochTime_r17, "NTN-CONFIG sent in dedicated mode should have EPOCHTIME\n"); + nr_rrc_process_ntnconfig(rrc, &rrc->perNB[gNB_index].SInfo, ntncfg, rrc->current_frame); + } } -void nr_rrc_cellgroup_configuration(NR_UE_RRC_INST_t *rrc, NR_CellGroupConfig_t *cellGroupConfig) +void nr_rrc_cellgroup_configuration(NR_UE_RRC_INST_t *rrc, NR_CellGroupConfig_t *cellGroupConfig, int gNB_index) { NR_SpCellConfig_t *spCellConfig = cellGroupConfig->spCellConfig; if(spCellConfig) { if (spCellConfig->reconfigurationWithSync) { LOG_I(NR_RRC, "Processing reconfigurationWithSync\n"); - nr_rrc_process_reconfigurationWithSync(rrc, spCellConfig->reconfigurationWithSync); + nr_rrc_process_reconfigurationWithSync(rrc, spCellConfig->reconfigurationWithSync, gNB_index); } nr_rrc_handle_SetupRelease_RLF_TimersAndConstants(rrc, spCellConfig->rlf_TimersAndConstants); if (spCellConfig->spCellConfigDedicated) { @@ -1074,10 +1228,10 @@ void nr_rrc_cellgroup_configuration(NR_UE_RRC_INST_t *rrc, NR_CellGroupConfig_t AssertFatal(cellGroupConfig->sCellToAddModList == NULL, "Secondary serving cell addition not implemented\n"); } - static void nr_rrc_ue_process_masterCellGroup(NR_UE_RRC_INST_t *rrc, OCTET_STRING_t *masterCellGroup, - long *fullConfig) + long *fullConfig, + int gNB_index) { AssertFatal(!fullConfig, "fullConfig not supported yet\n"); NR_CellGroupConfig_t *cellGroupConfig = NULL; @@ -1091,7 +1245,7 @@ static void nr_rrc_ue_process_masterCellGroup(NR_UE_RRC_INST_t *rrc, xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void *) cellGroupConfig); } - nr_rrc_cellgroup_configuration(rrc, cellGroupConfig); + nr_rrc_cellgroup_configuration(rrc, cellGroupConfig, gNB_index); LOG_D(RRC, "Sending CellGroupConfig to MAC the pointer will be managed by mac\n"); MessageDef *msg = itti_alloc_new_message(TASK_RRC_NRUE, 0, NR_MAC_RRC_CONFIG_CG); @@ -1150,9 +1304,7 @@ static void nr_rrc_process_rrcsetup(NR_UE_RRC_INST_t *rrc, const NR_RRCSetup_t * } // perform the cell group configuration procedure in accordance with the received masterCellGroup - nr_rrc_ue_process_masterCellGroup(rrc, - &rrcSetup->criticalExtensions.choice.rrcSetup->masterCellGroup, - NULL); + nr_rrc_ue_process_masterCellGroup(rrc, &rrcSetup->criticalExtensions.choice.rrcSetup->masterCellGroup, NULL, 0); // perform the radio bearer configuration procedure in accordance with the received radioBearerConfig nr_rrc_ue_process_RadioBearerConfig(rrc, &rrcSetup->criticalExtensions.choice.rrcSetup->radioBearerConfig); @@ -1999,7 +2151,8 @@ void *rrc_nrue(void *notUsed) } break; case NRRRC_FRAME_PROCESS: - LOG_D(NR_RRC, "Received %s: frame %d\n", ITTI_MSG_NAME(msg_p), NRRRC_FRAME_PROCESS(msg_p).frame); + rrc->current_frame = NRRRC_FRAME_PROCESS(msg_p).frame; + LOG_D(NR_RRC, "Received %s: frame %d\n", ITTI_MSG_NAME(msg_p), rrc->current_frame); // increase the timers every 10ms (every new frame) nr_rrc_handle_timers(rrc); NR_UE_RRC_SI_INFO *SInfo = &rrc->perNB[NRRRC_FRAME_PROCESS(msg_p).gnb_id].SInfo; @@ -2043,7 +2196,14 @@ void *rrc_nrue(void *notUsed) if (bcch->is_bch) nr_rrc_ue_decode_NR_BCCH_BCH_Message(rrc, bcch->gnb_index, bcch->phycellid, bcch->ssb_arfcn, bcch->sdu, bcch->sdu_size); else - nr_rrc_ue_decode_NR_BCCH_DL_SCH_Message(rrc, bcch->gnb_index, bcch->sdu, bcch->sdu_size, bcch->rsrq, bcch->rsrp); + nr_rrc_ue_decode_NR_BCCH_DL_SCH_Message(rrc, + bcch->gnb_index, + bcch->sdu, + bcch->sdu_size, + bcch->rsrq, + bcch->rsrp, + bcch->frame, + bcch->slot); break; case NR_RRC_MAC_SBCCH_DATA_IND: diff --git a/openair2/RRC/NR_UE/rrc_defs.h b/openair2/RRC/NR_UE/rrc_defs.h index e428c4c160..71645be31a 100644 --- a/openair2/RRC/NR_UE/rrc_defs.h +++ b/openair2/RRC/NR_UE/rrc_defs.h @@ -151,6 +151,11 @@ typedef struct UE_RRC_SI_INFO_NR_s { bool sib14_validity; NR_timer_t sib14_timer; NR_UE_RRC_SI_INFO_r17 SInfo_r17; + // Extracted from SIB1 + int scs; + int sib19_periodicity; + int sib19_windowposition; + int si_windowlength; } NR_UE_RRC_SI_INFO; typedef struct NR_UE_Timers_Constants_s { @@ -167,6 +172,8 @@ typedef struct NR_UE_Timers_Constants_s { NR_timer_t T325; NR_timer_t T380; NR_timer_t T390; + // NTN timer T430 which guards UL SYNC + NR_timer_t T430; // counters uint32_t N310_cnt; uint32_t N311_cnt; @@ -233,6 +240,8 @@ typedef struct NR_UE_RRC_INST_s { bool reconfig_after_reestab; // 5G-S-TMSI uint64_t fiveG_S_TMSI; + // Frame timing received from MAC + int current_frame; //Sidelink params NR_SL_PreconfigurationNR_r16_t *sl_preconfig; diff --git a/openair2/RRC/NR_UE/rrc_proto.h b/openair2/RRC/NR_UE/rrc_proto.h index f4728f0f58..9d599d6ab1 100644 --- a/openair2/RRC/NR_UE/rrc_proto.h +++ b/openair2/RRC/NR_UE/rrc_proto.h @@ -47,7 +47,7 @@ void init_nsa_message (NR_UE_RRC_INST_t *rrc, char* reconfig_file, char* rbconfi void process_nsa_message(NR_UE_RRC_INST_t *rrc, nsa_message_t nsa_message_type, void *message, int msg_len); -void nr_rrc_cellgroup_configuration(NR_UE_RRC_INST_t *rrc, NR_CellGroupConfig_t *cellGroupConfig); +void nr_rrc_cellgroup_configuration(NR_UE_RRC_INST_t *rrc, NR_CellGroupConfig_t *cellGroupConfig, int gNB_index); void nr_rrc_going_to_IDLE(NR_UE_RRC_INST_t *rrc, NR_Release_Cause_t release_cause, diff --git a/openair2/RRC/NR_UE/rrc_timers_and_constants.c b/openair2/RRC/NR_UE/rrc_timers_and_constants.c index 6629055b3a..9f46fbb3cd 100644 --- a/openair2/RRC/NR_UE/rrc_timers_and_constants.c +++ b/openair2/RRC/NR_UE/rrc_timers_and_constants.c @@ -169,6 +169,14 @@ void nr_rrc_handle_timers(NR_UE_RRC_INST_t *rrc) // with release cause 'RRC connection failure' nr_rrc_going_to_IDLE(rrc, RRC_CONNECTION_FAILURE, NULL); } + + bool t430_expired = nr_timer_tick(&rrc->timers_and_constants.T430); + if (t430_expired && rrc->nrRrcState == RRC_STATE_CONNECTED_NR && rrc->is_NTN_UE) { + LOG_W(NR_RRC, "Timer T430 expired! NTN UL SYNC FAILURE\n"); + // Upon T430 expiry, the UE shall reacquire SIB19 and re-obtain UL-SYNC + // Spec 38.331 Section 5.2.2.6 + AssertFatal(1 == 0, "UL-Sync Lost. Read SIB19, perform RACH and obtain UL-SYNC. NOT YET Implemented.\n"); + } } int nr_rrc_get_T304(long t304) From 7877e38890c294dc7d551c0a1a31718a2cd6e409 Mon Sep 17 00:00:00 2001 From: Raghavendra Dinavahi Date: Mon, 12 May 2025 20:23:55 +0200 Subject: [PATCH 31/35] UE changes: Handle T430 expiry in RRC, MAC SPEC 38.331 section 5.2.2.6 Inform MAC that UL SYNC got lost because of T430 expiry - Send message NR_MAC_RRC_CONFIG_RESET with cause UL_SYNC_LOST_T430_EXPIRY to MAC Reacquire SIB19 after T430 expiry This is not checked in this commit - RACH needs to be performed through probably PDCCH order to reobtain UL-SYNC - system usecase involving Recovery from T430 expiry not tested yet as that requires changes on gNB side. --- openair2/LAYER2/NR_MAC_UE/config_ue.c | 5 +++++ openair2/LAYER2/NR_MAC_UE/mac_defs.h | 3 ++- openair2/LAYER2/NR_MAC_UE/mac_proto.h | 1 + openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 21 +++++++++++++++++++ openair2/RRC/NR_UE/rrc_UE.c | 16 ++++++++++++++ openair2/RRC/NR_UE/rrc_proto.h | 1 + openair2/RRC/NR_UE/rrc_timers_and_constants.c | 4 ++-- 7 files changed, 48 insertions(+), 3 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index 3a5d5e5640..e86599ef18 100644 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -1718,6 +1718,11 @@ void nr_rrc_mac_config_req_reset(module_id_t module_id, NR_UE_MAC_reset_cause_t sync_req.ssb_bw_scan = false; nr_ue_send_synch_request(mac, module_id, 0, &sync_req); break; + case UL_SYNC_LOST_T430_EXPIRED: + // TS 38.331 Section 5.2.2.6, TS 38.321 Section 5.2a + // Flush all HARQ buffers and Stop UL transmissions + handle_ulsync_loss(mac); + break; default: AssertFatal(false, "Invalid MAC reset cause %d\n", cause); } diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index b3ca280f86..fcf770a2f4 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -196,7 +196,8 @@ typedef enum { GO_TO_IDLE, DETACH, T300_EXPIRY, - RE_ESTABLISHMENT + RE_ESTABLISHMENT, + UL_SYNC_LOST_T430_EXPIRED } NR_UE_MAC_reset_cause_t; typedef struct { diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index f5e36bd7d5..d12b006d90 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -323,6 +323,7 @@ void nr_Msg3_transmitted(NR_UE_MAC_INST_t *mac, uint8_t CC_id, frame_t frameP, s void trigger_MAC_UE_RA(NR_UE_MAC_INST_t *mac, dci_pdu_rel15_t *pdcch_order); void nr_get_Msg3_MsgA_PUSCH_payload(NR_UE_MAC_INST_t *mac, uint8_t *buf, int TBS_max); void handle_time_alignment_timer_expired(NR_UE_MAC_INST_t *mac); +void handle_ulsync_loss(NR_UE_MAC_INST_t *mac); int8_t nr_ue_process_dci_freq_dom_resource_assignment(nfapi_nr_ue_pusch_pdu_t *pusch_config_pdu, fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config_pdu, NR_PDSCH_Config_t *pdsch_Config, diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index 2c94de6e70..82f1669fa7 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -182,6 +182,27 @@ void handle_time_alignment_timer_expired(NR_UE_MAC_INST_t *mac) // TODO not sure what to do here } +void handle_ulsync_loss(NR_UE_MAC_INST_t *mac) +{ + // flush all HARQ buffers for all Serving Cells + for (int k = 0; k < NR_MAX_HARQ_PROCESSES; k++) { + memset(&mac->dl_harq_info[k], 0, sizeof(*mac->dl_harq_info)); + memset(&mac->ul_harq_info[k], 0, sizeof(*mac->ul_harq_info)); + mac->dl_harq_info[k].last_ndi = -1; // initialize to invalid value + mac->ul_harq_info[k].last_ndi = -1; // initialize to invalid value + } + // clear any configured downlink assignments and uplink grants; + if (mac->dl_config_request) + memset(mac->dl_config_request, 0, sizeof(*mac->dl_config_request)); + if (mac->ul_config_request) + clear_ul_config_request(mac); + + // Need to receive SIB19 again after loosing UL SYNC + mac->state = UE_RECEIVING_SIB; + // gNB needs to send PDCCH ORDER triggering RA after detecting ULSYNC LOSS + LOG_W(NR_MAC, "Wait for PDCCH ORDER, RACH needs to performed to obtain ULSYNC.\n"); +} + void update_mac_dl_timers(NR_UE_MAC_INST_t *mac) { bool ra_window_expired = nr_timer_tick(&mac->ra.response_window_timer); diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 17eaca5e9c..668a008d15 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -2801,6 +2801,22 @@ void handle_t300_expiry(NR_UE_RRC_INST_t *rrc) // TODO inform upper layers about the failure to establish the RRC connection } +void handle_t430_expiry(NR_UE_RRC_INST_t *rrc) +{ + // SPEC 38.331 section 5.2.2.6 + // Reacquire SIB19 after T430 expiry + for (int i = 0; i < NB_CNX_UE; i++) { + rrcPerNB_t *nb = &rrc->perNB[i]; + NR_UE_RRC_SI_INFO *SI_info = &nb->SInfo; + SI_info->SInfo_r17.sib19_validity = false; + } + // Indicate MAC that UL SYNC is LOST + NR_UE_MAC_reset_cause_t cause = UL_SYNC_LOST_T430_EXPIRED; + MessageDef *msg = itti_alloc_new_message(TASK_RRC_NRUE, 0, NR_MAC_RRC_CONFIG_RESET); + NR_MAC_RRC_CONFIG_RESET(msg).cause = cause; + itti_send_msg_to_task(TASK_MAC_UE, rrc->ue_id, msg); +} + //This calls the sidelink preconf message after RRC, MAC instances are created. void start_sidelink(int instance) { diff --git a/openair2/RRC/NR_UE/rrc_proto.h b/openair2/RRC/NR_UE/rrc_proto.h index 9d599d6ab1..7c5f749fa0 100644 --- a/openair2/RRC/NR_UE/rrc_proto.h +++ b/openair2/RRC/NR_UE/rrc_proto.h @@ -80,6 +80,7 @@ void init_SI_timers(NR_UE_RRC_SI_INFO *SInfo); void nr_ue_rrc_timer_trigger(int module_id, int frame, int gnb_id); void handle_t300_expiry(NR_UE_RRC_INST_t *rrc); +void handle_t430_expiry(NR_UE_RRC_INST_t *rrc); void reset_rlf_timers_and_constants(NR_UE_Timers_Constants_t *tac); void set_default_timers_and_constants(NR_UE_Timers_Constants_t *tac); diff --git a/openair2/RRC/NR_UE/rrc_timers_and_constants.c b/openair2/RRC/NR_UE/rrc_timers_and_constants.c index 9f46fbb3cd..9286494f0b 100644 --- a/openair2/RRC/NR_UE/rrc_timers_and_constants.c +++ b/openair2/RRC/NR_UE/rrc_timers_and_constants.c @@ -172,10 +172,10 @@ void nr_rrc_handle_timers(NR_UE_RRC_INST_t *rrc) bool t430_expired = nr_timer_tick(&rrc->timers_and_constants.T430); if (t430_expired && rrc->nrRrcState == RRC_STATE_CONNECTED_NR && rrc->is_NTN_UE) { - LOG_W(NR_RRC, "Timer T430 expired! NTN UL SYNC FAILURE\n"); + LOG_W(NR_RRC, "Timer T430 expired! Indicate UL SYNC LOSS to MAC\n"); // Upon T430 expiry, the UE shall reacquire SIB19 and re-obtain UL-SYNC // Spec 38.331 Section 5.2.2.6 - AssertFatal(1 == 0, "UL-Sync Lost. Read SIB19, perform RACH and obtain UL-SYNC. NOT YET Implemented.\n"); + handle_t430_expiry(rrc); } } From 97d0b6534aff42e1ce4466523c29f1771553e885 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 16 Jun 2025 19:01:53 +0200 Subject: [PATCH 32/35] Implement generic CI step "may_fail" option There might be various occasions where a CI step should be attempted to be executed, despite a chance of failing. For instance, we might want to try executing an instable Iperf test, and still mark the CI as passing if it fails. This commit introduces a generic "may_fail" option that will mark any CI test as succeeded, despite having failed. Ideally, we would print a warning in the HTML code, but this is not possible because each step emits its own HTML code, instead of the main loop handling this. We can improve this in the future. --- ci-scripts/main.py | 5 ++++- ci-scripts/tests/test-runner/test.xml | 19 +++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/ci-scripts/main.py b/ci-scripts/main.py index 333d515858..7aef60fa2a 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -626,6 +626,7 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re HTML.testCase_id=CiTestObj.testCase_id CiTestObj.desc = test.findtext('desc') always_exec = test.findtext('always_exec') in ['True', 'true', 'Yes', 'yes'] + may_fail = test.findtext('may_fail') in ['True', 'true', 'Yes', 'yes'] HTML.desc=CiTestObj.desc action = test.findtext('class') if (CheckClassValidity(xml_class_list, action, id) == False): @@ -639,7 +640,9 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re break try: test_succeeded = ExecuteActionWithParam(action) - if not test_succeeded: + if not test_succeeded and may_fail: + logging.warning(f"test ID {test_case_id} action {action} may or may not fail, proceeding despite error") + elif not test_succeeded: logging.error(f"test ID {test_case_id} action {action} failed ({test_succeeded}), skipping next tests") task_set_succeeded = False except Exception as e: diff --git a/ci-scripts/tests/test-runner/test.xml b/ci-scripts/tests/test-runner/test.xml index d5efacfdae..ec2515ec11 100644 --- a/ci-scripts/tests/test-runner/test.xml +++ b/ci-scripts/tests/test-runner/test.xml @@ -27,6 +27,8 @@ wrench 000001 + 000011 + 000012 000002 000003 000004 @@ -41,6 +43,23 @@ yes + + Custom_Command + This may fail + true + localhost + false + yes + + + + Custom_Command + This is still executed + localhost + true + yes + + Custom_Command This should fail From 79448178cba646a5d0813a6491f8c87dd62340ac Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 16 Jun 2025 19:12:42 +0200 Subject: [PATCH 33/35] Remove "command_fail" option from Custom_Command/Custom_Script As of the parent commit, there is a generic "may_fail" option through which we could still ignore an error. Thus, command_fail is superfluous, and avoids some extra code. Further, in all these cases, we should better be informed about any error, so let's not use may_fail for these tests. --- ci-scripts/cls_oaicitest.py | 14 ++++---------- ci-scripts/main.py | 6 ++---- ci-scripts/ran.py | 1 - ci-scripts/tests/test-runner/test.xml | 6 ------ ci-scripts/xml_files/container_5g_f1_rfsim.xml | 10 ---------- ci-scripts/xml_files/container_5g_rfsim_24prb.xml | 2 -- .../xml_files/container_5g_rfsim_sidelink.xml | 1 - ci-scripts/xml_files/container_sa_b200_quectel.xml | 2 -- .../xml_files/container_sa_e1_b200_quectel.xml | 2 -- .../xml_files/container_sa_f1_b200_quectel.xml | 2 -- .../container_sa_fhi72_metanoia_up2_2x2.xml | 2 -- .../xml_files/container_sa_fhi72_vvdn_up2.xml | 2 -- .../xml_files/container_sa_sc_b200_quectel.xml | 2 -- 13 files changed, 6 insertions(+), 46 deletions(-) diff --git a/ci-scripts/cls_oaicitest.py b/ci-scripts/cls_oaicitest.py index 4d7cf0a6fd..53bdacaacc 100644 --- a/ci-scripts/cls_oaicitest.py +++ b/ci-scripts/cls_oaicitest.py @@ -213,7 +213,7 @@ def Iperf_analyzeV2UDP(server_filename, iperf_bitrate_threshold, iperf_packetlos pal_msg += f' (too high! >{iperf_packetloss_threshold}%)' return (result, f'{req_msg}\n{bir_msg}\n{brl_msg}\n{jit_msg}\n{pal_msg}') -def Custom_Command(HTML, node, command, command_fail): +def Custom_Command(HTML, node, command): logging.info(f"Executing custom command on {node}") cmd = cls_cmd.getConnection(node) ret = cmd.run(command) @@ -221,26 +221,20 @@ def Custom_Command(HTML, node, command, command_fail): logging.debug(f"Custom_Command: {command} on node: {node} - {'OK, command succeeded' if ret.returncode == 0 else f'Error, return code: {ret.returncode}'}") status = 'OK' message = [] - if ret.returncode != 0 and not command_fail: - message = [ret.stdout] - logging.warning(f'Custom_Command output: {message}') - status = 'Warning' - if ret.returncode != 0 and command_fail: + if ret.returncode != 0: message = [ret.stdout] logging.error(f'Custom_Command failed: output: {message}') status = 'KO' HTML.CreateHtmlTestRowQueue(command, status, message) return status == 'OK' or status == 'Warning' -def Custom_Script(HTML, node, script, command_fail): +def Custom_Script(HTML, node, script): logging.info(f"Executing custom script on {node}") ret = cls_cmd.runScript(node, script, 90) logging.debug(f"Custom_Script: {script} on node: {node} - return code {ret.returncode}, output:\n{ret.stdout}") status = 'OK' message = [ret.stdout] - if ret.returncode != 0 and not command_fail: - status = 'Warning' - if ret.returncode != 0 and command_fail: + if ret.returncode != 0: status = 'KO' HTML.CreateHtmlTestRowQueue(script, status, message) return status == 'OK' or status == 'Warning' diff --git a/ci-scripts/main.py b/ci-scripts/main.py index 7aef60fa2a..18956ae28f 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -376,14 +376,12 @@ def ExecuteActionWithParam(action): # Change all execution targets to localhost node = 'localhost' command = test.findtext('command') - command_fail = test.findtext('command_fail') in ['True', 'true', 'Yes', 'yes'] - success = cls_oaicitest.Custom_Command(HTML, node, command, command_fail) + success = cls_oaicitest.Custom_Command(HTML, node, command) elif action == 'Custom_Script': node = test.findtext('node') script = test.findtext('script') - command_fail = test.findtext('command_fail') in ['True', 'true', 'Yes', 'yes'] - success = cls_oaicitest.Custom_Script(HTML, node, script, command_fail) + success = cls_oaicitest.Custom_Script(HTML, node, script) elif action == 'Pull_Cluster_Image': tag_prefix = test.findtext('tag_prefix') or "" diff --git a/ci-scripts/ran.py b/ci-scripts/ran.py index 6f58478476..f0f790ba2c 100644 --- a/ci-scripts/ran.py +++ b/ci-scripts/ran.py @@ -95,7 +95,6 @@ class RANManagement(): self.cmd_prefix = '' # prefix before {lte,nr}-softmodem self.node = '' self.command = '' - self.command_fail = False #----------------------------------------------------------- diff --git a/ci-scripts/tests/test-runner/test.xml b/ci-scripts/tests/test-runner/test.xml index ec2515ec11..cb54989301 100644 --- a/ci-scripts/tests/test-runner/test.xml +++ b/ci-scripts/tests/test-runner/test.xml @@ -40,7 +40,6 @@ This should succeed localhost true - yes @@ -49,7 +48,6 @@ true localhost false - yes @@ -57,7 +55,6 @@ This is still executed localhost true - yes @@ -65,7 +62,6 @@ This should fail localhost false - yes @@ -73,7 +69,6 @@ This should be skipped localhost true - yes @@ -82,6 +77,5 @@ true localhost true - yes diff --git a/ci-scripts/xml_files/container_5g_f1_rfsim.xml b/ci-scripts/xml_files/container_5g_f1_rfsim.xml index b27b0b5701..3b783a9215 100644 --- a/ci-scripts/xml_files/container_5g_f1_rfsim.xml +++ b/ci-scripts/xml_files/container_5g_f1_rfsim.xml @@ -134,7 +134,6 @@ Simulate a DL radio channel with noise (3 dB) cacofonix echo channelmod modify 0 noise_power_dB 3 | nc --send-only 192.168.71.181 8091 - yes @@ -166,7 +165,6 @@ Trigger Reestablishment cacofonix echo ci force_reestab | nc 192.168.71.171 9090 | grep -E 'Reset RLC counters of UE RNTI [0-9a-f]{4} to trigger reestablishment' - yes @@ -185,7 +183,6 @@ Verify Reestablishment cacofonix echo ci get_reestab_count | nc 192.168.71.150 9090 | grep -E 'UE RNTI [0-9a-f]{4} reestab 1' - yes @@ -193,7 +190,6 @@ Simulate a disruption of DL radio channel (ploss 55) cacofonix echo channelmod modify 0 ploss 55 | nc 192.168.71.181 8091 - yes @@ -201,7 +197,6 @@ Get UE sync state (UE ID 0) cacofonix echo ciUE sync_state 0 | nc 192.168.71.181 8091 | grep -E UE_NOT_SYNC - yes @@ -209,7 +204,6 @@ Restoration of the original DL channel conditions (ploss 20) cacofonix echo channelmod modify 0 ploss 20 | nc 192.168.71.181 8091 - yes @@ -217,7 +211,6 @@ Get UE sync state (UE ID 0) cacofonix echo ciUE sync_state 0 | nc 192.168.71.181 8091 | grep -E UE_CONNECTED - yes @@ -225,7 +218,6 @@ Trigger Handover cacofonix echo ci trigger_f1_ho | nc 192.168.71.150 9090 - yes @@ -233,7 +225,6 @@ UE (1) connected to DU-PCI 0? cacofonix echo ci fetch_du_by_ue_id 1 | nc 192.168.71.150 9090 | grep "3584" - yes @@ -241,7 +232,6 @@ UE (1) connected to DU-PCI 1? cacofonix echo ci fetch_du_by_ue_id 1 | nc 192.168.71.150 9090 | grep "3585" - yes diff --git a/ci-scripts/xml_files/container_5g_rfsim_24prb.xml b/ci-scripts/xml_files/container_5g_rfsim_24prb.xml index 5a59880b2f..91275a5f10 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_24prb.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_24prb.xml @@ -151,7 +151,6 @@ Force Msg3 C-RNTI RA cacofonix echo ciUE force_crnti_ra | nc 192.168.71.150 8091 - yes @@ -159,7 +158,6 @@ Force RRC_IDLE (UE ID 0) cacofonix echo ciUE force_RRC_IDLE | nc 192.168.71.150 8091 - yes diff --git a/ci-scripts/xml_files/container_5g_rfsim_sidelink.xml b/ci-scripts/xml_files/container_5g_rfsim_sidelink.xml index 133d960c3a..ac7e28f003 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_sidelink.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_sidelink.xml @@ -79,7 +79,6 @@ Check that UE synched cacofonix docker logs rfsim5g-oai-nr-ue-2 | grep -m 1 "PSBCH RX:OK" - yes diff --git a/ci-scripts/xml_files/container_sa_b200_quectel.xml b/ci-scripts/xml_files/container_sa_b200_quectel.xml index 9f3559aff1..dacee9692f 100644 --- a/ci-scripts/xml_files/container_sa_b200_quectel.xml +++ b/ci-scripts/xml_files/container_sa_b200_quectel.xml @@ -200,14 +200,12 @@ Trigger Reestablishment ofqot echo ci force_reestab | nc -N 127.0.0.1 9090 | grep -E 'Reset RLC counters of UE RNTI [0-9a-f]{4} to trigger reestablishment' - yes Custom_Command Verify Reestablishment ofqot echo ci get_reestab_count | nc -N 127.0.0.1 9090 | grep -E 'UE RNTI [0-9a-f]{4} reestab 1' - yes 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 dcbcb9a45f..b9535e6ea4 100644 --- a/ci-scripts/xml_files/container_sa_e1_b200_quectel.xml +++ b/ci-scripts/xml_files/container_sa_e1_b200_quectel.xml @@ -188,14 +188,12 @@ Trigger Reestablishment (on DU) ofqot echo ci force_reestab | nc -N 127.0.0.1 9091 | 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 127.0.0.1 9090 | grep -E 'UE RNTI [0-9a-f]{4} reestab 1' - yes diff --git a/ci-scripts/xml_files/container_sa_f1_b200_quectel.xml b/ci-scripts/xml_files/container_sa_f1_b200_quectel.xml index 9622b2cf13..fd935be551 100644 --- a/ci-scripts/xml_files/container_sa_f1_b200_quectel.xml +++ b/ci-scripts/xml_files/container_sa_f1_b200_quectel.xml @@ -233,14 +233,12 @@ Trigger Reestablishment (on DU) ofqot echo ci force_reestab | nc -N 127.0.0.1 9091 | 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 127.0.0.1 9090 | grep -E 'UE RNTI [0-9a-f]{4} reestab 1' - yes diff --git a/ci-scripts/xml_files/container_sa_fhi72_metanoia_up2_2x2.xml b/ci-scripts/xml_files/container_sa_fhi72_metanoia_up2_2x2.xml index e71ec3e37c..2b784b1fb6 100644 --- a/ci-scripts/xml_files/container_sa_fhi72_metanoia_up2_2x2.xml +++ b/ci-scripts/xml_files/container_sa_fhi72_metanoia_up2_2x2.xml @@ -49,7 +49,6 @@ Setup sriov and network interfaces Metanoia cacofonix - yes @@ -166,7 +165,6 @@ Set CPU to idle state, set kernel parameters to default values cacofonix - yes diff --git a/ci-scripts/xml_files/container_sa_fhi72_vvdn_up2.xml b/ci-scripts/xml_files/container_sa_fhi72_vvdn_up2.xml index 4afe8f1b12..3d1f337455 100644 --- a/ci-scripts/xml_files/container_sa_fhi72_vvdn_up2.xml +++ b/ci-scripts/xml_files/container_sa_fhi72_vvdn_up2.xml @@ -49,7 +49,6 @@ Setup sriov and network interfaces VVDN cacofonix - yes @@ -164,7 +163,6 @@ Set CPU to idle state, set kernel parameters to default values cacofonix - yes diff --git a/ci-scripts/xml_files/container_sa_sc_b200_quectel.xml b/ci-scripts/xml_files/container_sa_sc_b200_quectel.xml index 69201ebcc8..f116e97e24 100644 --- a/ci-scripts/xml_files/container_sa_sc_b200_quectel.xml +++ b/ci-scripts/xml_files/container_sa_sc_b200_quectel.xml @@ -194,14 +194,12 @@ Trigger Reestablishment ofqot echo ci force_reestab | nc -N 127.0.0.1 9090 | grep -E 'Reset RLC counters of UE RNTI [0-9a-f]{4} to trigger reestablishment' - yes Custom_Command Verify Reestablishment ofqot echo ci get_reestab_count | nc -N 127.0.0.1 9090 | grep -E 'UE RNTI [0-9a-f]{4} reestab 1' - yes From 02608313fb2ec6c3d16bbf3ffe81ce641ac9a96f Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 16 Jun 2025 19:20:04 +0200 Subject: [PATCH 34/35] CI: remove useless Iperf test description "multi-ue profile" was a specific iperf option to do iperf across multiple UEs. However, this is not necessary anymore, the Iperf handling multiple UEs "implicitly" (based on the number of UEs). --- ci-scripts/xml_files/container_sa_aw2s_asue.xml | 8 ++++---- ci-scripts/xml_files/container_sa_aw2s_asue_2x2.xml | 8 ++++---- .../xml_files/container_sa_fhi72_metanoia_up2_2x2.xml | 8 ++++---- ci-scripts/xml_files/container_sa_fhi72_vvdn_up2.xml | 8 ++++---- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/ci-scripts/xml_files/container_sa_aw2s_asue.xml b/ci-scripts/xml_files/container_sa_aw2s_asue.xml index 7eb6411827..88ab941e31 100644 --- a/ci-scripts/xml_files/container_sa_aw2s_asue.xml +++ b/ci-scripts/xml_files/container_sa_aw2s_asue.xml @@ -182,7 +182,7 @@ Iperf - iperf (DL/3Mbps/UDP)(30 sec)(multi-ue profile) + iperf (DL/3Mbps/UDP)(30 sec) -u -b 45M -t 30 -R amarisoft_ue_1 amarisoft_ue_2 amarisoft_ue_3 amarisoft_ue_4 amarisoft_ue_5 amarisoft_ue_6 amarisoft_ue_7 amarisoft_ue_8 amarisoft_ue_9 amarisoft_ue_10 amarisoft_ue_11 amarisoft_ue_12 amarisoft_ue_13 amarisoft_ue_14 amarisoft_ue_15 25 @@ -193,7 +193,7 @@ Iperf - iperf (DL/TCP)(30 sec)(multi-ue profile) + iperf (DL/TCP)(30 sec) -t 30 -R amarisoft_ue_1 amarisoft_ue_2 amarisoft_ue_3 amarisoft_ue_4 amarisoft_ue_5 amarisoft_ue_6 amarisoft_ue_7 amarisoft_ue_8 amarisoft_ue_9 amarisoft_ue_10 amarisoft_ue_11 amarisoft_ue_12 amarisoft_ue_13 amarisoft_ue_14 amarisoft_ue_15 2 @@ -202,7 +202,7 @@ Iperf - iperf (UL/1Mbps/UDP)(30 sec)(multi-ue profile) + iperf (UL/1Mbps/UDP)(30 sec) -u -b 15M -t 30 amarisoft_ue_1 amarisoft_ue_2 amarisoft_ue_3 amarisoft_ue_4 amarisoft_ue_5 amarisoft_ue_6 amarisoft_ue_7 amarisoft_ue_8 amarisoft_ue_9 amarisoft_ue_10 amarisoft_ue_11 amarisoft_ue_12 amarisoft_ue_13 amarisoft_ue_14 amarisoft_ue_15 25 @@ -213,7 +213,7 @@ Iperf - iperf (UL/TCP)(30 sec)(multi-ue profile) + iperf (UL/TCP)(30 sec) -t 30 oc-cn5g amarisoft_ue_1 amarisoft_ue_2 amarisoft_ue_3 amarisoft_ue_4 amarisoft_ue_5 amarisoft_ue_6 amarisoft_ue_7 amarisoft_ue_8 amarisoft_ue_9 amarisoft_ue_10 amarisoft_ue_11 amarisoft_ue_12 amarisoft_ue_13 amarisoft_ue_14 amarisoft_ue_15 diff --git a/ci-scripts/xml_files/container_sa_aw2s_asue_2x2.xml b/ci-scripts/xml_files/container_sa_aw2s_asue_2x2.xml index 739534be21..ed4a219f55 100644 --- a/ci-scripts/xml_files/container_sa_aw2s_asue_2x2.xml +++ b/ci-scripts/xml_files/container_sa_aw2s_asue_2x2.xml @@ -179,7 +179,7 @@ Iperf - iperf (DL/4Mbps/UDP)(30 sec)(multi-ue profile) + iperf (DL/4Mbps/UDP)(30 sec) -u -b 60M -t 30 -R amarisoft_ue_1 amarisoft_ue_2 amarisoft_ue_3 amarisoft_ue_4 amarisoft_ue_5 amarisoft_ue_6 amarisoft_ue_7 amarisoft_ue_8 amarisoft_ue_9 amarisoft_ue_10 amarisoft_ue_11 amarisoft_ue_12 amarisoft_ue_13 amarisoft_ue_14 amarisoft_ue_15 25 @@ -190,7 +190,7 @@ Iperf - iperf (DL/TCP)(30 sec)(multi-ue profile) + iperf (DL/TCP)(30 sec) -t 30 -R amarisoft_ue_1 amarisoft_ue_2 amarisoft_ue_3 amarisoft_ue_4 amarisoft_ue_5 amarisoft_ue_6 amarisoft_ue_7 amarisoft_ue_8 amarisoft_ue_9 amarisoft_ue_10 amarisoft_ue_11 amarisoft_ue_12 amarisoft_ue_13 amarisoft_ue_14 amarisoft_ue_15 3.9 @@ -199,7 +199,7 @@ Iperf - iperf (UL/1.5Mbps/UDP)(30 sec)(multi-ue profile) + iperf (UL/1.5Mbps/UDP)(30 sec) -u -b 22.5M -t 30 amarisoft_ue_1 amarisoft_ue_2 amarisoft_ue_3 amarisoft_ue_4 amarisoft_ue_5 amarisoft_ue_6 amarisoft_ue_7 amarisoft_ue_8 amarisoft_ue_9 amarisoft_ue_10 amarisoft_ue_11 amarisoft_ue_12 amarisoft_ue_13 amarisoft_ue_14 amarisoft_ue_15 25 @@ -210,7 +210,7 @@ Iperf - iperf (UL/TCP)(30 sec)(multi-ue profile) + iperf (UL/TCP)(30 sec) -t 30 oc-cn5g amarisoft_ue_1 amarisoft_ue_2 amarisoft_ue_3 amarisoft_ue_4 amarisoft_ue_5 amarisoft_ue_6 amarisoft_ue_7 amarisoft_ue_8 amarisoft_ue_9 amarisoft_ue_10 amarisoft_ue_11 amarisoft_ue_12 amarisoft_ue_13 amarisoft_ue_14 amarisoft_ue_15 diff --git a/ci-scripts/xml_files/container_sa_fhi72_metanoia_up2_2x2.xml b/ci-scripts/xml_files/container_sa_fhi72_metanoia_up2_2x2.xml index 2b784b1fb6..742b09e3d8 100644 --- a/ci-scripts/xml_files/container_sa_fhi72_metanoia_up2_2x2.xml +++ b/ci-scripts/xml_files/container_sa_fhi72_metanoia_up2_2x2.xml @@ -91,7 +91,7 @@ Iperf - iperf (DL/570Mbps/UDP)(30 sec)(multi-ue profile) + iperf (DL/570Mbps/UDP)(30 sec) -u -b 570M -t 30 -R up2-fhi72 20 @@ -102,7 +102,7 @@ Iperf - iperf (DL/TCP)(30 sec)(multi-ue profile) + iperf (DL/TCP)(30 sec) -t 30 -R up2-fhi72 80 @@ -111,7 +111,7 @@ Iperf - iperf (UL/100Mbps/UDP)(30 sec)(multi-ue profile) + iperf (UL/100Mbps/UDP)(30 sec) -u -b 100M -t 30 up2-fhi72 20 @@ -122,7 +122,7 @@ Iperf - iperf (UL/TCP)(30 sec)(multi-ue profile) + iperf (UL/TCP)(30 sec) -t 30 up2-fhi72 80 diff --git a/ci-scripts/xml_files/container_sa_fhi72_vvdn_up2.xml b/ci-scripts/xml_files/container_sa_fhi72_vvdn_up2.xml index 3d1f337455..64aa2d5648 100644 --- a/ci-scripts/xml_files/container_sa_fhi72_vvdn_up2.xml +++ b/ci-scripts/xml_files/container_sa_fhi72_vvdn_up2.xml @@ -89,7 +89,7 @@ Iperf - iperf (DL/600Mbps/UDP)(30 sec)(multi-ue profile) + iperf (DL/600Mbps/UDP)(30 sec) -u -b 600M -t 30 -R up2-fhi72 20 @@ -100,7 +100,7 @@ Iperf - iperf (DL/TCP)(30 sec)(multi-ue profile) + iperf (DL/TCP)(30 sec) -t 30 -R up2-fhi72 40 @@ -109,7 +109,7 @@ Iperf - iperf (UL/80Mbps/UDP)(30 sec)(multi-ue profile) + iperf (UL/80Mbps/UDP)(30 sec) -u -b 80M -t 30 up2-fhi72 20 @@ -120,7 +120,7 @@ Iperf - iperf (UL/TCP)(30 sec)(multi-ue profile) + iperf (UL/TCP)(30 sec) -t 30 up2-fhi72 10 From 7fb44bdb86d169838f96230a7aa119aad581550b Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 16 Jun 2025 19:22:40 +0200 Subject: [PATCH 35/35] CI FHI7.2/VVDN: add test step to test high throughput This test may fail, so mark it as such. --- ci-scripts/xml_files/container_sa_fhi72_vvdn_up2.xml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/ci-scripts/xml_files/container_sa_fhi72_vvdn_up2.xml b/ci-scripts/xml_files/container_sa_fhi72_vvdn_up2.xml index 64aa2d5648..1d7cd323e4 100644 --- a/ci-scripts/xml_files/container_sa_fhi72_vvdn_up2.xml +++ b/ci-scripts/xml_files/container_sa_fhi72_vvdn_up2.xml @@ -36,6 +36,7 @@ 100020 100030 100040 + 100011 103000 100002 130000 @@ -98,6 +99,17 @@ oc-cn5g-20897 + + Iperf + Optional iperf (DL/700Mbps/UDP)(30 sec) + true + -u -b 700M -t 30 -R + up2-fhi72 + 10 + 95 + oc-cn5g-20897 + + Iperf iperf (DL/TCP)(30 sec)